source: rtems-docs/porting/porting_old_reference_only.rst @ 36def91

4.115
Last change on this file since 36def91 was 489740f, checked in by Chris Johns <chrisj@…>, on 05/20/16 at 02:47:09

Set SPDX License Identifier in each source file.

  • Property mode set to 100644
File size: 75.3 KB
Line 
1.. comment SPDX-License-Identifier: CC-BY-SA-4.0
2
3:orphan:
4
5
6
7.. COMMENT: %**end of header
8
9.. COMMENT: COPYRIGHT (c) 1989-2013.
10
11.. COMMENT: On-Line Applications Research Corporation (OAR).
12
13.. COMMENT: All rights reserved.
14
15.. COMMENT: Master file for the Porting Guide
16
17.. COMMENT: Joel's Questions
18
19.. COMMENT: 1.  Why does paragraphindent only impact makeinfo?
20
21.. COMMENT: 2.  Why does paragraphindent show up in HTML?
22
23.. COMMENT: COPYRIGHT (c) 1988-2002.
24
25.. COMMENT: On-Line Applications Research Corporation (OAR).
26
27.. COMMENT: All rights reserved.
28
29.. COMMENT: The following determines which set of the tables and figures we will use.
30
31.. COMMENT: We default to ASCII but if available TeX or HTML versions will
32
33.. COMMENT: be used instead.
34
35.. COMMENT: @clear use-html
36
37.. COMMENT: @clear use-tex
38
39.. COMMENT: The following variable says to use texinfo or html for the two column
40
41.. COMMENT: texinfo tables.  For somethings the format does not look good in html.
42
43.. COMMENT: With our adjustment to the left column in TeX, it nearly always looks
44
45.. COMMENT: good printed.
46
47.. COMMENT: Custom whitespace adjustments.  We could fiddle a bit more.
48
49.. COMMENT: variable substitution info:
50
51.. COMMENT: the language is @value{LANGUAGE}
52
53.. COMMENT: NOTE:  don't use underscore in the name
54
55.. COMMENT: Title Page Stuff
56
57.. COMMENT: I don't really like having a short title page.  -joel
58
59.. COMMENT: @shorttitlepage RTEMS Porting Guide
60
61===================
62RTEMS Porting Guide
63===================
64
65.. COMMENT: COPYRIGHT (c) 1988-2015.
66
67.. COMMENT: On-Line Applications Research Corporation (OAR).
68
69.. COMMENT: All rights reserved.
70
71.. COMMENT: The following puts a space somewhere on an otherwise empty page so we
72
73.. COMMENT: can force the copyright description onto a left hand page.
74
75COPYRIGHT © 1988 - 2015.
76
77On-Line Applications Research Corporation (OAR).
78
79The authors have used their best efforts in preparing
80this material.  These efforts include the development, research,
81and testing of the theories and programs to determine their
82effectiveness.  No warranty of any kind, expressed or implied,
83with regard to the software or the material contained in this
84document is provided.  No liability arising out of the
85application or use of any product described in this document is
86assumed.  The authors reserve the right to revise this material
87and to make changes from time to time in the content hereof
88without obligation to notify anyone of such revision or changes.
89
90The RTEMS Project is hosted at http://www.rtems.org.  Any
91inquiries concerning RTEMS, its related support components, or its
92documentation should be directed to the Community Project hosted athttp://www.rtems.org.
93
94Any inquiries for commercial services including training, support, custom
95development, application development assistance should be directed tohttp://www.rtems.com.
96
97.. COMMENT: This prevents a black box from being printed on "overflow" lines.
98
99.. COMMENT: The alternative is to rework a sentence to avoid this problem.
100
101RTEMS Porting Guide
102###################
103
104.. COMMENT: COPYRIGHT (c) 1989-2011.
105
106.. COMMENT: On-Line Applications Research Corporation (OAR).
107
108.. COMMENT: All rights reserved.
109
110Preface
111#######
112
113The purpose of this manual is to provide a roadmap to those people porting
114RTEMS to a new CPU family. This process includes a variety of activities
115including the following:
116
117- targeting the GNU development tools
118
119- porting the RTEMS executive code
120
121- developing a Board Support Package
122
123- writing an RTEMS CPU Supplement manual for the completed port.
124
125This document focuses on the process of actually porting the RTEMS
126executive code proper.  Each of the data structures, routines, and macro
127definitions required of a port of RTEMS is described in this document.
128
129Porting any operating system, including RTEMS, requires knowledge of the
130operating system, target CPU architecture, and debug environment.  It is
131very desirable to have a CPU simulator or hardware emulator when debugging
132the port.  This manual assumes that the user is familiar with building and
133using RTEMS, the C programming language, and the target CPU architecture.
134It is desirable to be familiar with the assembly language for the target
135CPU family but since only a limited amount of assembly is required to port
136RTEMS.
137
138.. COMMENT: COPYRIGHT (c) 1988-2002.
139
140.. COMMENT: On-Line Applications Research Corporation (OAR).
141
142.. COMMENT: All rights reserved.
143
144Development Tools
145#################
146
147When porting RTEMS to a new CPU architecture, one will have to have a
148development environment including compiler, assembler, linker, and
149debugger.  The GNU development tool suite used by RTEMS supports most
150modern CPU families.  Often all that is required is to add RTEMS
151configurations for the target CPU family.  RTEMS targets for the GNU tools
152usually start life as little more than aliases for existing embedded
153configurations.  At this point in time, ELF is supported on most of the
154CPU families with a tool target of the form CPU-elf.  If this target is
155not supported by all of the GNU tools, then it will be necessary to
156determine the configuration that makes the best starting point regardless
157of the target object format.
158
159Porting and retargetting the GNU tools is beyond the scope of this manual.
160The best advice that can be offered is to look at the existing RTEMS
161targets in the tool source and use that as a guideline.
162
163.. COMMENT: COPYRIGHT (c) 1988-2002.
164
165.. COMMENT: On-Line Applications Research Corporation (OAR).
166
167.. COMMENT: All rights reserved.
168
169Source Code Organization
170########################
171
172This section describes the organization of the source code within RTEMS
173that is CPU family and CPU model dependent.
174
175Introduction
176============
177
178The CPU family dependent files associated with a port of the RTEMS
179executive code proper to a particular processor family are found in
180cpukit/score/cpu.  Support code for this port as well as processor
181dependent code which may be reused across multiple Board Support Packages
182is found in c/src/lib/libcpu.
183
184XXX list the files and directories here
185
186.. COMMENT: COPYRIGHT (c) 1988-2002.
187
188.. COMMENT: On-Line Applications Research Corporation (OAR).
189
190.. COMMENT: All rights reserved.
191
192CPU Model Variations
193####################
194
195XXX enhance using portability presentation from CS595 class.  See
196general/portability.ppt.
197
198Since the text in the next section was written, RTEMS view of
199portability has grown to distinguish totally portable, CPU
200family dependent, CPU model dependent, peripheral chip dependent
201and board dependent.  This text was part of a larger paper that
202did not even cover portability completely as it existed when this
203was written and certainly is out of date now. :)
204
205Overview of RTEMS Portability
206=============================
207
208RTEMS was designed to be a highly portable, reusable software component.
209This reflects the fundamental nature of embedded systems in which hardware
210components, ranging from boards to peripherals to even the processor
211itself, are selected specifically to meet the requirements of a particular
212project.
213
214Processor Families
215------------------
216
217Since there are a wide variety of embedded systems, there are a wide
218variety of processors targeting embedded systems. RTEMS alleviates some of
219the burden on the embedded systems programmer by providing a consistent,
220high-performance environment regardless of the target processor.  RTEMS
221has been ported to a variety of microprocessor families including:
222
223- Motorola ColdFire
224
225- Motorola MC68xxx
226
227- Motorola MC683xx
228
229- Intel ix86 (i386, i486, Pentium and above)
230
231- ARM
232
233- MIPS
234
235- PowerPC 4xx, 5xx, 6xx, 7xx, 8xx, and 84xx
236
237- SPARC
238
239- Hitachi H8/300
240
241- Hitachi SH
242
243- OpenCores OR32
244
245- Texas Instruments C3x/C4x
246
247In addition, there is a port of RTEMS to UNIX that uses standard UNIX
248services to simulate the embedded environment.
249
250Each RTEMS port supplies a well-defined set of services that are the
251foundation for the highly portable RTEMS and POSIX API implementations.
252When porting to a new processor family, one must provide the processor
253dependent implementation of these services.  This set of processor
254dependent core services includes software to perform interrupt
255dispatching, context switches, and manipulate task register sets.
256
257The RTEMS approach to handling varying processor models reflects the
258approach taken by the designers of the processors themselves.  In each
259processor family, there is a core architecture that must be implemented on
260all processor models within the family to provide any level of
261compatibility.  Many of the modern RISC architectures refer to this as the
262Architectural Definition.  The Architectural Definition is intended to be
263independent of any particular implementation. Additionally, there is a
264feature set which is allowed to vary in a defined way amongst the
265processor models.  These feature sets may be defined as Optional in the
266Architectural Definition, be left as implementation defined
267characteristics, or be processor model specific extensions.  Support for
268floating point, virtual memory, and low power mode are common Optional
269features included in an Architectural Definition.
270
271The processor family dependent software in RTEMS includes a definition of
272which features are present in each supported processor model.  This often
273makes adding support for a new processor model within a supported family
274as simple as determining which features are present in the new processor
275implementation.  If the new processor model varies in a way previously
276unaccounted for, then this must be addressed.  This could be the result of
277a new Optional feature set being added to the Architectural Definition.
278Alternatively, this particular processor model could have a new and
279different implementation of a feature left as undefined in the
280Architectural Definition.  This would require software to be written to
281utilize that feature.
282
283There is a relatively small set of features that may vary in a processor
284family.  As the number of processor models in the family grow, the
285addition of each new model only requires adding an entry for the new model
286to the single feature table.  It does not require searching for every
287conditional based on processor model and adding the new model in the
288appropriate place.  This significantly eases the burden of adding a new
289processor model as it centralizes and logically simplifies the process.
290
291Boards
292------
293
294Being portable both between models within a processor family and across
295processor families is not enough to address the needs of embedded systems
296developers.  Custom board development is the norm for embedded systems.
297Each of these boards is optimized for a particular project.  The processor
298and peripheral set have been chosen to meet a particular set of system
299requirements.  The tools in the embedded systems developers’ toolbox must
300support their project’s unique board.  RTEMS addresses this issue via the
301Board Support Package.
302
303RTEMS segregates board specific code to make it possible for the embedded
304systems developer to easily replace and customize this software.  A
305minimal Board Support Package includes device drivers for a clock tick,
306console I/O, and a benchmark timer (optional) as well as startup and
307miscellaneous support code.  The Board Support Package for a project may
308be extended to include the device drivers for any peripherals on the
309custom board.
310
311Applications
312------------
313
314One important design goal of RTEMS was to provide a bridge between the
315application software and the target hardware.  Most hardware dependencies
316for real-time applications can be localized to the low level device
317drivers which provide an abstracted view of the hardware.  The RTEMS I/O
318interface manager provides an efficient tool for incorporating these
319hardware dependencies into the system while simultaneously providing a
320general mechanism to the application code that accesses them.  A well
321designed real-time system can benefit from this architecture by building a
322rich library of standard application components which can be used
323repeatedly in other real-time projects. The following figure illustrates
324how RTEMS serves as a buffer between the project dependent application
325code and the target hardware.
326
327Coding Issues
328=============
329
330XXX deal with this as it applies to score/cpu.  Section name may
331be bad.
332
333.. COMMENT: COPYRIGHT (c) 1988-2002.
334
335.. COMMENT: On-Line Applications Research Corporation (OAR).
336
337.. COMMENT: All rights reserved.
338
339CPU Initialization
340##################
341
342This section describes the general CPU and system initialization sequence
343as it pertains to the CPU dependent code.
344
345Introduction
346============
347
348XXX general startup sequence description rewritten to make it more
349applicable to CPU depdent code in executive
350
351Initializing the CPU
352====================
353
354The _CPU_Initialize routine performs processor dependent initialization.
355.. code:: c
356
357    void _CPU_Initialize(
358    void            (\*thread_dispatch)  /* may be ignored \*/
359    )
360
361The thread_dispatch argument is the address of the entry point for the
362routine called at the end of an ISR once it has been decided a context
363switch is necessary.  On some compilation systems it is difficult to call
364a high-level language routine from assembly.  Providing the address of the
365_Thread_ISR_Dispatch routine allows the porter an easy way to obtain this
366critical address and thus provides an easy way to work around this
367limitation on these systems.
368
369If you encounter this problem save the entry point in a CPU dependent
370variable as shown below:
371.. code:: c
372
373    _CPU_Thread_dispatch_pointer = thread_dispatch;
374
375During the initialization of the context for tasks with floating point,
376the CPU dependent code is responsible for initializing the floating point
377context.  If there is not an easy way to initialize the FP context during
378Context_Initialize, then it is usually easier to save an "uninitialized"
379FP context here and copy it to the task’s during Context_Initialize.  If
380this technique is used to initialize the FP contexts, then it is important
381to ensure that the state of the floating point unit is in a coherent,
382initialized state.
383
384.. COMMENT: COPYRIGHT (c) 1988-2002.
385
386.. COMMENT: On-Line Applications Research Corporation (OAR).
387
388.. COMMENT: All rights reserved.
389
390Interrupts
391##########
392
393Introduction
394============
395
396Interrupt Levels
397================
398
399RTEMS is designed assuming that a CPU family has a level associated with
400interrupts.  Interrupts below the current interrupt level are masked and
401do not interrupt the CPU until the interrupt level is lowered.  This
402design provides for 256 distinct interrupt levels even though most CPU
403implementations support far fewer levels.  Interrupt level 0 is assumed to
404map to the hardware settings for all interrupts enabled.
405
406Over the years that RTEMS has been available, there has been much
407discussion on how to handle CPU families which support very few interrupt
408levels such as the i386, PowerPC, and HP-PA RISC. XXX
409
410Interrupt Level Mask
411--------------------
412
413The CPU_MODES_INTERRUPT_MASK macro defines the number of bits actually used in the interrupt field of the task mode.  How those bits map to the CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
414
415The following illustrates how the CPU_MODES_INTERRUPT_MASK is set on a CPU
416family like the Intel i386 where the CPU itself only recognizes two
417interrupt levels - enabled and disabled.
418.. code:: c
419
420    #define CPU_MODES_INTERRUPT_MASK   0x00000001
421
422Obtaining the Current Interrupt Level
423-------------------------------------
424
425The _CPU_ISR_Get_level function returns the current interrupt level.
426.. code:: c
427
428    uint32_t _CPU_ISR_Get_level( void )
429
430Set the Interrupt Level
431-----------------------
432
433The _CPU_ISR_Set_level routine maps the interrupt level in the Classic API
434task mode onto the hardware that the CPU actually provides.  Currently,
435interrupt levels that do not map onto the CPU in a generic fashion are
436undefined.  Someday, it would be nice if these were "mapped" by the
437application via a callout.  For example, the Motorola m68k has 8 levels 0
438- 7, and levels 8 - 255 are currently undefined.  Levels 8 - 255 would be
439available for bsp/application specific meaning. This could be used to
440manage a programmable interrupt controller via the rtems_task_mode
441directive.
442
443The following is a dummy implementation of the _CPU_ISR_Set_level routine:
444.. code:: c
445
446    #define _CPU_ISR_Set_level( new_level ) \\
447    { \\
448    }
449
450The following is the implementation from the Motorola M68K:
451.. code:: c
452
453    XXX insert m68k implementation here
454
455Disable Interrupts
456------------------
457
458The _CPU_ISR_Disable routine disable all external interrupts.  It returns
459the previous interrupt level in the single parameter _isr_cookie.  This
460routine is used to disable interrupts during a critical section in the
461RTEMS executive.  Great care is taken inside the executive to ensure that
462interrupts are disabled for a minimum length of time.  It is important to
463note that the way the previous level is returned forces the implementation
464to be a macro that translates to either inline assembly language or a
465function call whose return value is placed into _isr_cookie.
466
467It is important for the porter to realize that the value of _isr_cookie
468has no defined meaning except that it is the most convenient format for
469the _CPU_ISR_Disable, _CPU_ISR_Enable, and _CPU_ISR_Disable routines to
470manipulate.  It is typically the contents of the processor status
471register.  It is NOT the same format as manipulated by the
472_CPU_ISR_Get_level and _CPU_ISR_Set_level routines. The following is a
473dummy implementation that simply sets the previous level to 0.
474.. code:: c
475
476    #define _CPU_ISR_Disable( _isr_cookie ) \\
477    { \\
478    (_isr_cookie) = 0;   /* do something to prevent warnings \*/ \\
479    }
480
481The following is the implementation from the Motorola M68K port:
482.. code:: c
483
484    XXX insert m68k port here
485
486Enable Interrupts
487-----------------
488
489The _CPU_ISR_Enable routines enables interrupts to the previous level
490(returned by _CPU_ISR_Disable).  This routine is invoked at the end of an
491RTEMS critical section to reenable interrupts.  The parameter _level is
492not modified but indicates that level that interrupts should be enabled
493to.  The following illustrates a dummy implementation of the
494_CPU_ISR_Enable routine:
495.. code:: c
496
497    #define _CPU_ISR_Enable( _isr_cookie )  \\
498    { \\
499    }
500
501The following is the implementation from the Motorola M68K port:
502.. code:: c
503
504    XXX insert m68k version here
505
506Flash Interrupts
507----------------
508
509The _CPU_ISR_Flash routine temporarily restores the interrupt to _level
510before immediately disabling them again.  This is used to divide long
511RTEMS critical sections into two or more parts.  This routine is always
512preceded by a call to _CPU_ISR_Disable and followed by a call to
513_CPU_ISR_Enable.  The parameter _level is not modified.
514
515The following is a dummy implementation of the _CPU_ISR_Flash routine:
516.. code:: c
517
518    #define _CPU_ISR_Flash( _isr_cookie ) \\
519    { \\
520    }
521
522The following is the implementation from the Motorola M68K port:
523.. code:: c
524
525    XXX insert m68k version here
526
527Interrupt Stack Management
528==========================
529
530Hardware or Software Managed Interrupt Stack
531--------------------------------------------
532
533The setting of the CPU_HAS_SOFTWARE_INTERRUPT_STACK indicates whether the
534interrupt stack is managed by RTEMS in software or the CPU has direct
535support for an interrupt stack.  If RTEMS is to manage a dedicated
536interrupt stack in software, then this macro should be set to TRUE and the
537memory for the software managed interrupt stack is allocated in``_ISR_Handler_initialization``.  If this macro is set to FALSE, then
538RTEMS assumes that the hardware managed interrupt stack is supported by
539this CPU.  If the CPU has a hardware managed interrupt stack, then the
540porter has the option of letting the BSP allcoate and initialize the
541interrupt stack or letting RTEMS do this.  If RTEMS is to allocate the
542memory for the interrupt stack, then the macro
543CPU_ALLOCATE_INTERRUPT_STACK should be set to TRUE.  If this macro is set
544to FALSE, then it is the responsibility of the BSP to allocate the memory
545for this stack and initialize it.
546
547If the CPU does not support a dedicated interrupt stack, then the porter
548has two options: (1) execute interrupts on the stack of the interrupted
549task, and (2) have RTEMS manage a dedicated interrupt stack.
550
551NOTE: If CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE, then the macro
552CPU_ALLOCATE_INTERRUPT_STACK should also be set to TRUE.
553
554Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
555CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE.  It is possible
556that both are FALSE for a particular CPU.  Although it is unclear what
557that would imply about the interrupt processing procedure on that CPU.
558
559Allocation of Interrupt Stack Memory
560------------------------------------
561
562Whether or not the interrupt stack is hardware or software managed, RTEMS
563may allocate memory for the interrupt stack from the Executive Workspace.
564If RTEMS is going to allocate the memory for a dedicated interrupt stack
565in the Interrupt Manager, then the macro CPU_ALLOCATE_INTERRUPT_STACK
566should be set to TRUE.
567
568NOTE: This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE.
569.. code:: c
570
571    #define CPU_ALLOCATE_INTERRUPT_STACK TRUE
572
573If the CPU_HAS_SOFTWARE_INTERRUPT_STACK macro is set to TRUE, then RTEMS automatically allocates the stack memory in the initialization of the Interrupt Manager and the switch to that stack is performed in ``_ISR_Handler`` on the outermost interrupt.  The _CPU_Interrupt_stack_low and _CPU_Interrupt_stack_high variables contain the addresses of the the lowest and highest addresses of the memory allocated for the interrupt stack.  Although technically only one of these addresses is required to switch to the interrupt stack, by always providing both addresses, the port has more options avaialble to it without requiring modifications to the portable parts of the executive.  Whether the stack  grows up or down, this give the CPU dependent code the option of picking the version it wants to use.
574.. code:: c
575
576    SCORE_EXTERN void               \*_CPU_Interrupt_stack_low;
577    SCORE_EXTERN void               \*_CPU_Interrupt_stack_high;
578
579NOTE: These two variables are required if the macro
580CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
581
582Install the Interrupt Stack
583---------------------------
584
585The _CPU_Install_interrupt_stack routine XXX
586
587This routine installs the hardware interrupt stack pointer.
588
589NOTE:  It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STAC is TRUE.
590.. code:: c
591
592    void _CPU_Install_interrupt_stack( void )
593
594ISR Installation
595================
596
597Install a Raw Interrupt Handler
598-------------------------------
599
600The _CPU_ISR_install_raw_handler XXX
601.. code:: c
602
603    void _CPU_ISR_install_raw_handler(
604    unsigned32  vector,
605    proc_ptr    new_handler,
606    proc_ptr   \*old_handler
607    )
608
609This is where we install the interrupt handler into the "raw" interrupt
610table used by the CPU to dispatch interrupt handlers.
611
612Interrupt Context
613-----------------
614
615Maximum Number of Vectors
616-------------------------
617
618There are two related macros used to defines the number of entries in the
619_ISR_Vector_table managed by RTEMS.  The macro
620CPU_INTERRUPT_NUMBER_OF_VECTORS is the actual number of vectors supported
621by this CPU model.  The second macro is the
622CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER.  Since the table is zero-based, this
623indicates the highest vector number which can be looked up in the table
624and mapped into a user provided handler.
625.. code:: c
626
627    #define CPU_INTERRUPT_NUMBER_OF_VECTORS      32
628    #define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER \\
629    (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
630
631Install RTEMS Interrupt Handler
632-------------------------------
633
634The _CPU_ISR_install_vector routine installs the RTEMS handler for the
635specified vector.
636
637XXX Input parameters:
638vector      - interrupt vector number
639old_handler - former ISR for this vector number
640new_handler - replacement ISR for this vector number
641.. code:: c
642
643    void _CPU_ISR_install_vector(
644    unsigned32  vector,
645    proc_ptr    new_handler,
646    proc_ptr   \*old_handler
647    )
648
649.. code:: c
650
651    *old_handler = _ISR_Vector_table[ vector ];
652
653If the interrupt vector table is a table of pointer to isr entry points,
654then we need to install the appropriate RTEMS interrupt handler for this
655vector number.
656.. code:: c
657
658    _CPU_ISR_install_raw_handler( vector, new_handler, old_handler );
659
660We put the actual user ISR address in _ISR_vector_table.  This will be
661used by the ``_ISR_Handler`` so the user gets control.
662.. code:: c
663
664    _ISR_Vector_table[ vector ] = new_handler;
665
666Interrupt Processing
667====================
668
669Interrupt Frame Data Structure
670------------------------------
671
672When an interrupt occurs, it is the responsibility of the interrupt
673dispatching software to save the context of the processor such that an ISR
674written in a high-level language (typically C) can be invoked without
675damaging the state of the task that was interrupted.  In general, this
676results in the saving of registers which are NOT preserved across
677subroutine calls as well as any special interrupt state.  A port should
678define the ``CPU_Interrupt_frame`` structure so that application code can
679examine the saved state.
680.. code:: c
681
682    typedef struct {
683    unsigned32 not_preserved_register_1;
684    unsigned32 special_interrupt_register;
685    } CPU_Interrupt_frame;
686
687Interrupt Dispatching
688---------------------
689
690The ``_ISR_Handler`` routine provides the RTEMS interrupt management.
691.. code:: c
692
693    void _ISR_Handler()
694
695This discussion ignores a lot of the ugly details in a real implementation
696such as saving enough registers/state to be able to do something real.
697Keep in mind that the goal is to invoke a user’s ISR handler which is
698written in C.  That ISR handler uses a known set of registers thus
699allowing the ISR to preserve only those that would normally be corrupted
700by a subroutine call.
701
702Also note that the exact order is to a large extent flexible.  Hardware
703will dictate a sequence for a certain subset of ``_ISR_Handler`` while
704requirements for setting the RTEMS state variables that indicate the
705interrupt nest level (``_ISR_Nest_level``) and dispatching disable
706level (``_Thread_Dispatch_disable_level``) will also
707restrict the allowable order.
708
709Upon entry to ``_ISR_Handler``, ``_Thread_Dispatch_disable_level`` is
710zero if the interrupt occurred while outside an RTEMS service call.
711Conversely, it will be non-zero if interrupting an RTEMS service
712call.  Thus, ``_Thread_Dispatch_disable_level`` will always be
713greater than or equal to ``_ISR_Nest_level`` and not strictly
714equal.
715
716Upon entry to the "common" ``_ISR_Handler``, the vector number must be
717available.  On some CPUs the hardware puts either the vector number or the
718offset into the vector table for this ISR in a known place.  If the
719hardware does not provide this information, then the assembly portion of
720RTEMS for this port will contain a set of distinct interrupt entry points
721which somehow place the vector number in a known place (which is safe if
722another interrupt nests this one) and branches to ``_ISR_Handler``.
723.. code:: c
724
725    save some or all context on stack
726    may need to save some special interrupt information for exit
727    #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
728    if ( _ISR_Nest_level == 0 )
729    switch to software interrupt stack
730    #endif
731    _ISR_Nest_level++;
732    _Thread_Dispatch_disable_level++;
733    (\*_ISR_Vector_table[ vector ])( vector );
734    --_ISR_Nest_level;
735    if ( _ISR_Nest_level )
736    goto the label "exit interrupt (simple case)"
737    #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
738    restore stack
739    #endif
740    if ( _Thread_Dispatch_disable_level )
741    goto the label "exit interrupt (simple case)"
742    if ( _Thread_Dispatch_necessary )
743    call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
744    prepare to get out of interrupt
745    return from interrupt  (maybe to _ISR_Dispatch)
746    LABEL "exit interrupt (simple case):
747    prepare to get out of interrupt
748    return from interrupt
749
750Some ports have the special routine ``_ISR_Dispatch`` because
751the CPU has a special "interrupt mode" and RTEMS must switch back
752to the task stack and/or non-interrupt mode before invoking``_Thread_Dispatch``.  For example, consider the MC68020 where
753upon return from the outermost interrupt, the CPU must switch
754from the interrupt stack to the master stack before invoking``_Thread_Dispatch``.  ``_ISR_Dispatch`` is the special port
755specific wrapper for ``_Thread_Dispatch`` used in this case.
756
757ISR Invoked with Frame Pointer
758------------------------------
759
760Does the RTEMS invoke the user’s ISR with the vector number and a pointer
761to the saved interrupt frame (1) or just the vector number (0)?
762.. code:: c
763
764    #define CPU_ISR_PASSES_FRAME_POINTER 0
765
766NOTE: It is desirable to include a pointer to the interrupt stack frame as
767an argument to the interrupt service routine.  Eventually, it would be
768nice if all ports included this parameter.
769
770Pointer to _Thread_Dispatch Routine
771-----------------------------------
772
773With some compilation systems, it is difficult if not impossible to call a
774high-level language routine from assembly language.  This is especially
775true of commercial Ada compilers and name mangling C++ ones.  This
776variable can be optionally defined by the CPU porter and contains the
777address of the routine _Thread_Dispatch.  This can make it easier to
778invoke that routine at the end of the interrupt sequence (if a dispatch is
779necessary).
780.. code:: c
781
782    void (\*_CPU_Thread_dispatch_pointer)();
783
784.. COMMENT: COPYRIGHT (c) 1988-2002.
785
786.. COMMENT: On-Line Applications Research Corporation (OAR).
787
788.. COMMENT: All rights reserved.
789
790Task Context Management
791#######################
792
793Introduction
794============
795
796XXX
797
798Task Stacks
799===========
800
801XXX
802
803Direction of Stack Growth
804-------------------------
805
806The CPU_STACK_GROWS_UP macro is set based upon the answer to the following
807question: Does the stack grow up (toward higher addresses) or down (toward
808lower addresses)?  If the stack grows upward in memory, then this macro
809should be set to TRUE.  Otherwise, it should be set to FALSE to indicate
810that the stack grows downward toward smaller addresses.
811
812The following illustrates how the CPU_STACK_GROWS_UP macro is set:
813.. code:: c
814
815    #define CPU_STACK_GROWS_UP               TRUE
816
817Minimum Task Stack Size
818-----------------------
819
820The CPU_STACK_MINIMUM_SIZE macro should be set to the minimum size of each
821task stack.  This size is specified as the number of bytes.  This minimum
822stack size should be large enough to run all RTEMS tests.  The minimum
823stack size is chosen such that a "reasonable" small application should not
824have any problems.  Choosing a minimum stack size that is too small will
825result in the RTEMS tests "blowing" their stack and not executing
826properly.
827
828There are many reasons a task could require a stack size larger than the
829minimum.  For example, a task could have a very deep call path or declare
830large data structures on the stack.  Tasks which utilize C++ exceptions
831tend to require larger stacks as do Ada tasks.
832
833The following illustrates setting the minimum stack size to 4 kilobytes
834per task.
835.. code:: c
836
837    #define CPU_STACK_MINIMUM_SIZE          (1024*4)
838
839Stack Alignment Requirements
840----------------------------
841
842The CPU_STACK_ALIGNMENT macro is set to indicate the byte alignment
843requirement for the stack.  This alignment requirement may be stricter
844than that for the data types alignment specified by CPU_ALIGNMENT.  If the
845CPU_ALIGNMENT is strict enough for the stack, then this should be set to
8460.
847
848The following illustrates how the CPU_STACK_ALIGNMENT macro should be set
849when there are no special requirements:
850.. code:: c
851
852    #define CPU_STACK_ALIGNMENT        0
853
854NOTE:  This must be a power of 2 either 0 or greater than CPU_ALIGNMENT. \[XXX is this true?]
855
856Task Context
857============
858
859Associated with each task is a context that distinguishes it from other
860tasks in the system and logically gives it its own scratch pad area for
861computations.  In addition, when an interrupt occurs some processor
862context information must be saved and restored.  This is managed in RTEMS
863as three items:
864
865- Basic task level context (e.g. the Context_Control structure)
866
867- Floating point task context (e.g. Context_Control_fp structure)
868
869- Interrupt level context (e.g.  the Context_Control_interrupt
870  structure)
871
872The integer and floating point context structures and the routines that
873manipulate them are discussed in detail in this section, while the
874interrupt level context structure is discussed in the XXX.
875
876Additionally, if the GNU debugger gdb is to be made aware of RTEMS tasks
877for this CPU, then care should be used in designing the context area.
878.. code:: c
879
880    typedef struct {
881    unsigned32 special_interrupt_register;
882    } CPU_Interrupt_frame;
883
884Basic Context Data Structure
885----------------------------
886
887The Context_Control data structure contains the basic integer context of a
888task.  In addition, this context area contains stack and frame pointers,
889processor status register(s), and any other registers that are normally
890altered by compiler generated code.  In addition, this context must
891contain the processor interrupt level since the processor interrupt level
892is maintained on a per-task basis.  This is necessary to support the
893interrupt level portion of the task mode as provided by the Classic RTEMS
894API.
895
896On some processors, it is cost-effective to save only the callee preserved
897registers during a task context switch.  This means that the ISR code
898needs to save those registers which do not persist across function calls.
899It is not mandatory to make this distinctions between the caller/callee
900saves registers for the purpose of minimizing context saved during task
901switch and on interrupts.  If the cost of saving extra registers is
902minimal, simplicity is the choice.  Save the same context on interrupt
903entry as for tasks in this case.
904
905The Context_Control data structure should be defined such that the order
906of elements results in the simplest, most efficient implementation of XXX.
907A typical implementation starts with a definition such as the following:
908.. code:: c
909
910    typedef struct {
911    unsigned32 some_integer_register;
912    unsigned32 another_integer_register;
913    unsigned32 some_system_register;
914    } Context_Control;
915
916Initializing a Context
917----------------------
918
919The _CPU_Context_Initialize routine initializes the context to a state
920suitable for starting a task after a context restore operation.
921Generally, this involves:
922
923- setting a starting address,
924
925- preparing the stack,
926
927- preparing the stack and frame pointers,
928
929- setting the proper interrupt level in the context, and
930
931- initializing the floating point context
932
933This routine generally does not set any unnecessary register in the
934context.  The state of the "general data" registers is undefined at task
935start time. The _CPU_Context_initialize routine is prototyped as follows:
936.. code:: c
937
938    void _CPU_Context_Initialize(
939    Context_Control \*_the_context,
940    void            \*_stack_base,
941    unsigned32       _size,
942    unsigned32       _isr,
943    void            \*_entry_point,
944    unsigned32       _is_fp
945    );
946
947The ``is_fp`` parameter is TRUE if the thread is to be a floating point
948thread.  This is typically only used on CPUs where the FPU may be easily
949disabled by software such as on the SPARC where the PSR contains an enable
950FPU bit.  The use of an FPU enable bit allows RTEMS to ensure that a
951non-floating point task is unable to access the FPU.  This guarantees that
952a deferred floating point context switch is safe.
953
954The ``_stack_base`` parameter is the base address of the memory area
955allocated for use as the task stack.  It is critical to understand that``_stack_base`` may not be the starting stack pointer for this task.
956On CPU families where the stack grows from high addresses to lower ones,
957(i.e. ``CPU_STACK_GROWS_UP`` is FALSE) the starting stack point
958will be near the end of the stack memory area or close to``_stack_base`` + ``_size``.  Even on CPU families where the stack
959grows from low to higher addresses, there may be some required
960outermost stack frame that must be put at the address ``_stack_base``.
961
962The ``_size`` parameter is the requested size in bytes of the stack for
963this task.  It is assumed that the memory area ``_stack_base``
964is of this size.
965
966XXX explain other parameters and check prototype
967
968Performing a Context Switch
969---------------------------
970
971The _CPU_Context_switch performs a normal non-FP context switch from the
972context of the current executing thread to the context of the heir thread.
973.. code:: c
974
975    void _CPU_Context_switch(
976    Context_Control  \*run,
977    Context_Control  \*heir
978    );
979
980This routine begins by saving the current state of the
981CPU (i.e. the context) in the context area at ``run``.
982Then the routine should load the CPU context pointed to
983by ``heir``.  Loading the new context will cause a
984branch to its task code, so the task that invoked``_CPU_Context_switch`` will not run for a while.
985When, eventually, a context switch is made to load
986context from ``*run`` again, this task will resume
987and ``_CPU_Context_switch`` will return to its caller.
988
989Care should be exercise when writing this routine.  All
990registers assumed to be preserved across subroutine calls
991must be preserved.  These registers may be saved in
992the task’s context area or on its stack.  However, the
993stack pointer and address to resume executing the task
994at must be included in the context (normally the subroutine
995return address to the caller of ``_Thread_Dispatch``.
996The decision of where to store the task’s context is based
997on numerous factors including the capabilities of
998the CPU architecture itself and simplicity as well
999as external considerations such as debuggers wishing
1000to examine a task’s context.  In this case, it is
1001often simpler to save all data in the context area.
1002
1003Also there may be special considerations
1004when loading the stack pointers or interrupt level of the
1005incoming task.  Independent of CPU specific considerations,
1006if some context is saved on the task stack, then the porter
1007must ensure that the stack pointer is adjusted *BEFORE*
1008to make room for this context information before the
1009information is written.  Otherwise, an interrupt could
1010occur writing over the context data.  The following is
1011an example of an *INCORRECT* sequence:
1012.. code:: c
1013
1014    save part of context beyond current top of stack
1015    interrupt pushes context -- overwriting written context
1016    interrupt returns
1017    adjust stack pointer
1018
1019Restoring a Context
1020-------------------
1021
1022The _CPU_Context_restore routine is generally used only to restart the
1023currently executing thread (i.e. self) in an efficient manner.  In many
1024ports, it can simply be a label in _CPU_Context_switch. It may be
1025unnecessary to reload some registers.
1026.. code:: c
1027
1028    void _CPU_Context_restore(
1029    Context_Control \*new_context
1030    );
1031
1032Restarting the Currently Executing Task
1033---------------------------------------
1034
1035The _CPU_Context_Restart_self is responsible for somehow restarting the
1036currently executing task.  If you are lucky when porting RTEMS, then all
1037that is necessary is restoring the context.  Otherwise, there will need to
1038be a routine that does something special in this case.  Performing a
1039_CPU_Context_Restore on the currently executing task after reinitializing
1040that context should work on most ports.  It will not work if restarting
1041self conflicts with the stack frame assumptions of restoring a context.
1042
1043The following is an implementation of _CPU_Context_Restart_self that can
1044be used when no special handling is required for this case.
1045.. code:: c
1046
1047    #define _CPU_Context_Restart_self( _the_context ) \\
1048    _CPU_Context_restore( (_the_context) )
1049
1050XXX find a port which does not do it this way and include it here
1051
1052Floating Point Context
1053======================
1054
1055CPU_HAS_FPU Macro Definition
1056----------------------------
1057
1058The CPU_HAS_FPU macro is set based on the answer to the question: Does the
1059CPU have hardware floating point?  If the CPU has an FPU, then this should
1060be set to TRUE.  Otherwise, it should be set to FALSE.  The primary
1061implication of setting this macro to TRUE is that it indicates that tasks
1062may have floating point contexts.  In the Classic API, this means that the
1063RTEMS_FLOATING_POINT task attribute specified as part of rtems_task_create
1064is supported on this CPU.  If CPU_HAS_FPU is set to FALSE, then no tasks
1065or threads may be floating point and the RTEMS_FLOATING_POINT task
1066attribute is ignored.  On an API such as POSIX where all threads
1067implicitly have a floating point context, then the setting of this macro
1068determines whether every POSIX thread has a floating point context.
1069
1070The following example illustrates how the CPU_HARDWARE_FP (XXX macro name
1071is varying) macro is set based on the CPU family dependent macro.
1072.. code:: c
1073
1074    #if ( THIS_CPU_FAMILY_HAS_FPU == 1 ) /* where THIS_CPU_FAMILY \*/
1075    /* might be M68K \*/
1076    #define CPU_HARDWARE_FP     TRUE
1077    #else
1078    #define CPU_HARDWARE_FP     FALSE
1079    #endif
1080
1081The macro name THIS_CPU_FAMILY_HAS_FPU should be made CPU specific.  It
1082indicates whether or not this CPU model has FP support.  For example, the
1083definition of the i386ex and i386sx CPU models would set I386_HAS_FPU to
1084FALSE to indicate that these CPU models are i386’s without an i387 and
1085wish to leave floating point support out of RTEMS when built for the
1086i386_nofp processor model.  On a CPU with a built-in FPU like the i486,
1087this would be defined as TRUE.
1088
1089On some processor families, the setting of the THIS_CPU_FAMILY_HAS_FPU
1090macro may be derived from compiler predefinitions.  This can be used when
1091the compiler distinguishes the individual CPU models for this CPU family
1092as distinctly as RTEMS requires.  Often RTEMS needs to need more about the
1093CPU model than the compiler because of differences at the system level
1094such as caching, interrupt structure.
1095
1096CPU_ALL_TASKS_ARE_FP Macro Setting
1097----------------------------------
1098
1099The CPU_ALL_TASKS_ARE_FP macro is set to TRUE or FALSE based upon the
1100answer to the following question: Are all tasks RTEMS_FLOATING_POINT tasks
1101implicitly?  If this macro is set TRUE, then all tasks and threads are
1102assumed to have a floating point context.  In the Classic API, this is
1103equivalent to setting the RTEMS_FLOATING_POINT task attribute on all
1104rtems_task_create calls.  If the CPU_ALL_TASKS_ARE_FP macro is set to
1105FALSE, then the RTEMS_FLOATING_POINT task attribute in the Classic API is
1106honored.
1107
1108The rationale for this macro is that if a function that an application
1109developer would not think utilize the FP unit DOES, then one can not
1110easily predict which tasks will use the FP hardware. In this case, this
1111option should be TRUE.  So far, the only CPU families for which this macro
1112has been to TRUE are the HP PA-RISC and PowerPC.  For the HP PA-RISC, the
1113HP C compiler and gcc both implicitly use the floating point registers to
1114perform integer multiplies.  For the PowerPC, this feature macro is set to
1115TRUE because the printf routine saves a floating point register whether or
1116not a floating point number is actually printed.  If the newlib
1117implementation of printf were restructured to avoid this, then the PowerPC
1118port would not have to have this option set to TRUE.
1119
1120The following example illustrates how the CPU_ALL_TASKS_ARE_FP is set on
1121the PowerPC.  On this CPU family, this macro is set to TRUE if the CPU
1122model has hardware floating point.
1123.. code:: c
1124
1125    #if (CPU_HARDWARE_FP == TRUE)
1126    #define CPU_ALL_TASKS_ARE_FP     TRUE
1127    #else
1128    #define CPU_ALL_TASKS_ARE_FP     FALSE
1129    #endif
1130
1131NOTE: If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
1132
1133CPU_USE_DEFERRED_FP_SWITCH Macro Setting
1134----------------------------------------
1135
1136The CPU_USE_DEFERRED_FP_SWITCH macro is set based upon the answer to the
1137following question:  Should the saving of the floating point registers be
1138deferred until a context switch is made to another different floating
1139point task?  If the floating point context will not be stored until
1140necessary, then this macro should be set to TRUE.  When set to TRUE, the
1141floating point context of a task will remain in the floating point
1142registers and not disturbed until another floating point task is switched
1143to.
1144
1145If the CPU_USE_DEFERRED_FP_SWITCH is set to FALSE, then the floating point
1146context is saved each time a floating point task is switched out and
1147restored when the next floating point task is restored.  The state of the
1148floating point registers between those two operations is not specified.
1149
1150There are a couple of known cases where the port should not defer saving
1151the floating point context.  The first case is when the compiler generates
1152instructions that use the FPU when floating point is not actually used.
1153This occurs on the HP PA-RISC for example when an integer multiply is
1154performed.  On the PowerPC, the printf routine includes a save of a
1155floating point register to support printing floating point numbers even if
1156the path that actually prints the floating point number is not invoked.
1157In both of these cases, deferred floating point context switches can not
1158be used.  If the floating point context has to be saved as part of
1159interrupt dispatching, then it may also be necessary to disable deferred
1160context switches.
1161
1162Setting this flag to TRUE results in using a different algorithm for
1163deciding when to save and restore the floating point context.  The
1164deferred FP switch algorithm minimizes the number of times the FP context
1165is saved and restored.  The FP context is not saved until a context switch
1166is made to another, different FP task.  Thus in a system with only one FP
1167task, the FP context will never be saved or restored.
1168
1169The following illustrates setting the CPU_USE_DEFERRED_FP_SWITCH macro on
1170a processor family such as the M68K or i386 which can use deferred
1171floating point context switches.
1172.. code:: c
1173
1174    #define CPU_USE_DEFERRED_FP_SWITCH       TRUE
1175
1176Note that currently, when in SMP configuration, deferred floating point
1177context switching is unavailable.
1178
1179Floating Point Context Data Structure
1180-------------------------------------
1181
1182The Context_Control_fp contains the per task information for the floating
1183point unit.  The organization of this structure may be a list of floating
1184point registers along with any floating point control and status registers
1185or it simply consist of an array of a fixed number of bytes.  Defining the
1186floating point context area as an array of bytes is done when the floating
1187point context is dumped by a "FP save context" type instruction and the
1188format is either not completely defined by the CPU documentation or the
1189format is not critical for the implementation of the floating point
1190context switch routines.  In this case, there is no need to figure out the
1191exact format – only the size.  Of course, although this is enough
1192information for RTEMS, it is probably not enough for a debugger such as
1193gdb.  But that is another problem.
1194.. code:: c
1195
1196    typedef struct {
1197    double      some_float_register;
1198    } Context_Control_fp;
1199
1200On some CPUs with hardware floating point support, the Context_Control_fp
1201structure will not be used.
1202
1203Size of Floating Point Context Macro
1204------------------------------------
1205
1206The CPU_CONTEXT_FP_SIZE macro is set to the size of the floating point
1207context area. On some CPUs this will not be a "sizeof" because the format
1208of the floating point area is not defined – only the size is.  This is
1209usually on CPUs with a "floating point save context" instruction.  In
1210general, though it is easier to define the structure as a "sizeof"
1211operation and define the Context_Control_fp structure to be an area of
1212bytes of the required size in this case.
1213.. code:: c
1214
1215    #define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
1216
1217Start of Floating Point Context Area Macro
1218------------------------------------------
1219
1220The _CPU_Context_Fp_start macro is used in the XXX routine and allows the initial pointer into a  floating point context area (used to save the floating point context) to be at an arbitrary place in the floating point context area.  This is necessary because some FP units are designed to have their context saved as a stack which grows into lower addresses.  Other FP units can be saved by simply moving registers into offsets from the base of the context area.  Finally some FP units provide a "dump context" instruction which could fill in from high to low or low to high based on the whim of the CPU designers.  Regardless, the address at which that floating point context area pointer should start within the actual floating point context area varies between ports and this macro provides a clean way of addressing this.
1221
1222This is a common implementation of the _CPU_Context_Fp_start routine which
1223is suitable for many processors.  In particular, RISC processors tend to
1224use this implementation since the floating point context is saved as a
1225sequence of store operations.
1226.. code:: c
1227
1228    #define _CPU_Context_Fp_start( _base, _offset ) \\
1229    ( (void \*) _Addresses_Add_offset( (_base), (_offset) ) )
1230
1231In contrast, the m68k treats the floating point context area as a stack
1232which grows downward in memory.  Thus the following implementation of
1233_CPU_Context_Fp_start is used in that port:
1234
1235.. code:: c
1236
1237    XXX insert m68k version here
1238
1239Initializing a Floating Point Context
1240-------------------------------------
1241
1242The _CPU_Context_Initialize_fp routine initializes the floating point
1243context area passed to it to. There are a few standard ways in which to
1244initialize the floating point context.  The simplest, and least
1245deterministic behaviorally, is to do nothing.  This leaves the FPU in a
1246random state and is generally not a suitable way to implement this
1247routine.  The second common implementation is to place a "null FP status
1248word" into some status/control register in the FPU.  This mechanism is
1249simple and works on many FPUs.  Another common way is to initialize the
1250FPU to a known state during _CPU_Initialize and save the context (using
1251_CPU_Context_save_fp_context) into the special floating point context
1252_CPU_Null_fp_context.  Then all that is required to initialize a floating
1253point context is to copy _CPU_Null_fp_context to the destination floating
1254point context passed to it.  The following example implementation shows
1255how to accomplish this:
1256.. code:: c
1257
1258    #define _CPU_Context_Initialize_fp( _destination ) \\
1259    { \\
1260    \*((Context_Control_fp \*) \*((void \**) _destination)) = \\
1261    _CPU_Null_fp_context; \\
1262    }
1263
1264The _CPU_Null_fp_context is optional.  A port need only include this variable when it uses the above mechanism to initialize a floating point context.  This is typically done on CPUs where it is difficult to generate an "uninitialized" FP context.  If the port requires this variable, then it is declared as follows:
1265.. code:: c
1266
1267    Context_Control_fp  _CPU_Null_fp_context;
1268
1269Saving a Floating Point Context
1270-------------------------------
1271
1272The _CPU_Context_save_fp_context routine is responsible for saving the FP
1273context at \*fp_context_ptr.  If the point to load the FP context from is
1274changed then the pointer is modified by this routine.
1275
1276Sometimes a macro implementation of this is in cpu.h which dereferences
1277the \** and a similarly named routine in this file is passed something like
1278a (Context_Control_fp \*).  The general rule on making this decision is to
1279avoid writing assembly language.
1280.. code:: c
1281
1282    void _CPU_Context_save_fp(
1283    void \**fp_context_ptr
1284    )
1285
1286Restoring a Floating Point Context
1287----------------------------------
1288
1289The _CPU_Context_restore_fp_context is responsible for restoring the FP
1290context at \*fp_context_ptr.  If the point to load the FP context from is
1291changed then the pointer is modified by this routine.
1292
1293Sometimes a macro implementation of this is in cpu.h which dereferences
1294the \** and a similarly named routine in this file is passed something like
1295a (Context_Control_fp \*).  The general rule on making this decision is to
1296avoid writing assembly language.
1297.. code:: c
1298
1299    void _CPU_Context_restore_fp(
1300    void \**fp_context_ptr
1301    );
1302
1303.. COMMENT: COPYRIGHT (c) 1988-2002.
1304
1305.. COMMENT: On-Line Applications Research Corporation (OAR).
1306
1307.. COMMENT: All rights reserved.
1308
1309IDLE Thread
1310###########
1311
1312Does Idle Thread Have a Floating Point Context?
1313===============================================
1314
1315The setting of the macro CPU_IDLE_TASK_IS_FP is based on the answer to the
1316question:  Should the IDLE task have a floating point context?  If the
1317answer to this question is TRUE, then the IDLE task has a floating point
1318context associated.  This is equivalent to creating a task in the Classic
1319API (using rtems_task_create) as a RTEMS_FLOATING_POINT task.  If
1320CPU_IDLE_TASK_IS_FP is set to TRUE, then a floating point context switch
1321occurs when the IDLE task is switched in and out.  This adds to the
1322execution overhead of the system but is necessary on some ports.
1323
1324If FALSE, then the IDLE task does not have a floating point context.
1325
1326NOTE: Setting CPU_IDLE_TASK_IS_FP to TRUE negatively impacts the time
1327required to preempt the IDLE task from an interrupt because the floating
1328point context must be saved as part of the preemption.
1329
1330The following illustrates how to set this macro:
1331.. code:: c
1332
1333    #define CPU_IDLE_TASK_IS_FP      FALSE
1334
1335CPU Dependent Idle Thread Body
1336==============================
1337
1338CPU_PROVIDES_IDLE_THREAD_BODY Macro Setting
1339-------------------------------------------
1340
1341The CPU_PROVIDES_IDLE_THREAD_BODY macro setting is based upon the answer
1342to the question:  Does this port provide a CPU dependent IDLE task
1343implementation?  If the answer to this question is yes, then the
1344CPU_PROVIDES_IDLE_THREAD_BODY macro should be set to TRUE, and the routine
1345_CPU_Thread_Idle_body must be provided.  This routine overrides the
1346default IDLE thread body of _Thread_Idle_body.  If the
1347CPU_PROVIDES_IDLE_THREAD_BODY macro is set to FALSE, then the generic
1348_Thread_Idle_body is the default IDLE thread body for this port.
1349Regardless of whether or not a CPU dependent IDLE thread implementation is
1350provided, the BSP can still override it.
1351
1352This is intended to allow for supporting processors which have a low power
1353or idle mode.  When the IDLE thread is executed, then the CPU can be
1354powered down when the processor is idle.
1355
1356The order of precedence for selecting the IDLE thread body is:
1357
1358# BSP provided
1359
1360# CPU dependent (if provided)
1361
1362# generic (if no BSP and no CPU dependent)
1363
1364The following illustrates setting the CPU_PROVIDES_IDLE_THREAD_BODY macro:
1365.. code:: c
1366
1367    #define CPU_PROVIDES_IDLE_THREAD_BODY    TRUE
1368
1369Implementation details of a CPU model specific IDLE thread body are in the
1370next section.
1371
1372Idle Thread Body
1373----------------
1374
1375The _CPU_Thread_Idle_body routine only needs to be provided if the porter
1376wishes to include a CPU dependent IDLE thread body.  If the port includes
1377a CPU dependent implementation of the IDLE thread body, then the
1378CPU_PROVIDES_IDLE_THREAD_BODY macro should be defined to TRUE.  This
1379routine is prototyped as follows:
1380.. code:: c
1381
1382    void \*_CPU_Thread_Idle_body( uintptr_t );
1383
1384As mentioned above, RTEMS does not require that a CPU dependent IDLE
1385thread body be provided as part of the port.  If
1386CPU_PROVIDES_IDLE_THREAD_BODY is defined to FALSE, then the CPU
1387independent algorithm is used.  This algorithm consists of a "branch to
1388self" which is implemented in a routine as follows.
1389.. code:: c
1390
1391    void \*_Thread_Idle_body( uintptr_t ignored )
1392    {
1393    while( 1 ) ;
1394    }
1395
1396If the CPU dependent IDLE thread body is implementation centers upon using
1397a "halt", "idle", or "shutdown" instruction, then don’t forget to put it
1398in an infinite loop as the CPU will have to reexecute this instruction
1399each time the IDLE thread is dispatched.
1400.. code:: c
1401
1402    void \*_CPU_Thread_Idle_body( uintptr_t ignored )
1403    {
1404    for( ; ; )
1405    /* insert your "halt" instruction here \*/ ;
1406    }
1407
1408Be warned. Some processors with onboard DMA have been known to stop the
1409DMA if the CPU were put in IDLE mode.  This might also be a problem with
1410other on-chip peripherals.  So use this hook with caution.
1411
1412.. COMMENT: COPYRIGHT (c) 1988-2002.
1413
1414.. COMMENT: On-Line Applications Research Corporation (OAR).
1415
1416.. COMMENT: All rights reserved.
1417
1418Priority Bitmap Manipulation
1419############################
1420
1421Introduction
1422============
1423
1424The RTEMS chain of ready tasks is implemented as an array of FIFOs with
1425each priority having its own FIFO.  This makes it very efficient to
1426determine the first and last ready task at each priority.  In addition,
1427blocking a task only requires appending the task to the end of the FIFO
1428for its priority rather than a lengthy search down a single chain of all
1429ready tasks.  This works extremely well except for one problem.  When the
1430currently executing task blocks, there may be no easy way to determine
1431what is the next most important ready task.  If the blocking task was the
1432only ready task at its priority, then RTEMS must search all of the FIFOs
1433in the ready chain to determine the highest priority with a ready task.
1434
1435RTEMS uses a bitmap array to efficiently solve this problem.  The state of
1436each bit in the priority map bit array indicates whether or not there is a
1437ready task at that priority.  The bit array can be efficiently searched to
1438determine the highest priority ready task.  This family of data type and
1439routines is used to maintain and search the bit map array.
1440
1441When manipulating the bitmap array, RTEMS internally divides the
14428 bits of the task priority into "major" and "minor" components.
1443The most significant 4 bits are the major component, while the least
1444significant are the minor component.  The major component of a priority
1445value is used to determine which 16-bit wide entry in the``_Priority_Bit_map`` array is associated with this priority.
1446Each element in the ``_Priority_Bit_map`` array has a bit
1447in the ``_Priority_Major_bit_map`` associated with it.
1448That bit is cleared when all of the bits in a particular``_Priority_Bit_map`` array entry are zero.
1449
1450The minor component of a priority is used to determine
1451specifically which bit in ``_Priority_Bit_map[major]``
1452indicates whether or not there is a ready to execute task
1453at the priority.
1454
1455_Priority_bit_map_Control Type
1456==============================
1457
1458The ``_Priority_Bit_map_Control`` type is the fundamental data type of the
1459priority bit map array used to determine which priorities have ready
1460tasks.  This type may be either 16 or 32 bits wide although only the 16
1461least significant bits will be used.  The data type is based upon what is
1462the most efficient type for this CPU to manipulate.  For example, some
1463CPUs have bit scan instructions that only operate on a particular size of
1464data.  In this case, this type will probably be defined to work with this
1465instruction.
1466
1467Find First Bit Routine
1468======================
1469
1470The _CPU_Bitfield_Find_first_bit routine sets _output to the bit number of
1471the first bit set in ``_value``.  ``_value`` is of CPU dependent type``Priority_bit_map_Control``.  A stub version of this routine is as follows:
1472.. code:: c
1473
1474    #define _CPU_Bitfield_Find_first_bit( _value, _output ) \\
1475    { \\
1476    (_output) = 0;   /* do something to prevent warnings \*/ \\
1477    }
1478
1479There are a number of variables in using a "find first bit" type
1480instruction.
1481
1482# What happens when run on a value of zero?
1483
1484# Bits may be numbered from MSB to LSB or vice-versa.
1485
1486# The numbering may be zero or one based.
1487
1488# The "find first bit" instruction may search from MSB or LSB.
1489
1490RTEMS guarantees that (1) will never happen so it is not a concern.
1491Cases (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
1492_CPU_Priority_bits_index().  These three form a set of routines which must
1493logically operate together.  Bits in the ``_value`` are set and cleared based
1494on masks built by CPU_Priority_mask().  The basic major and minor values
1495calculated by _Priority_Major() and _Priority_Minor() are "massaged" by
1496_CPU_Priority_bits_index() to properly range between the values returned
1497by the "find first bit" instruction.  This makes it possible for
1498_Priority_Get_highest() to calculate the major and directly index into the
1499minor table.  This mapping is necessary to ensure that 0 (a high priority
1500major/minor) is the first bit found.
1501
1502This entire "find first bit" and mapping process depends heavily on the
1503manner in which a priority is broken into a major and minor components
1504with the major being the 4 MSB of a priority and minor the 4 LSB.  Thus (0
1505<< 4) + 0 corresponds to priority 0 – the highest priority.  And (15 <<
15064) + 14 corresponds to priority 254 – the next to the lowest priority.
1507
1508If your CPU does not have a "find first bit" instruction, then there are
1509ways to make do without it.  Here are a handful of ways to implement this
1510in software:
1511
1512- a series of 16 bit test instructions
1513
1514- a "binary search using if’s"
1515
1516- 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:
1517
1518  .. code:: c
1519
1520      _number = 0 if _value > 0x00ff
1521      _value >>=8
1522      _number = 8;
1523      if _value > 0x0000f
1524      _value >=8
1525      _number += 4
1526      _number += bit_set_table[ _value ]
1527
1528The following illustrates how the CPU_USE_GENERIC_BITFIELD_CODE macro may
1529be so the port can use the generic implementation of this bitfield code.
1530This can be used temporarily during the porting process to avoid writing
1531these routines until the end.  This results in a functional although lower
1532performance port.  This is perfectly acceptable during development and
1533testing phases.
1534.. code:: c
1535
1536    #define CPU_USE_GENERIC_BITFIELD_CODE TRUE
1537    #define CPU_USE_GENERIC_BITFIELD_DATA TRUE
1538
1539Eventually, CPU specific implementations of these routines are usually
1540written since they dramatically impact the performance of blocking
1541operations.  However they may take advantage of instructions which are not
1542available on all models in the CPU family.  In this case, one might find
1543something like this stub example did:
1544.. code:: c
1545
1546    #if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
1547    #define _CPU_Bitfield_Find_first_bit( _value, _output ) \\
1548    { \\
1549    (_output) = 0;   /* do something to prevent warnings \*/ \\
1550    }
1551    #endif
1552
1553Build Bit Field Mask
1554====================
1555
1556The _CPU_Priority_Mask routine builds the mask that corresponds to the bit
1557fields searched by _CPU_Bitfield_Find_first_bit().  See the discussion of
1558that routine for more details.
1559
1560The following is a typical implementation when the
1561_CPU_Bitfield_Find_first_bit searches for the most significant bit set:
1562.. code:: c
1563
1564    #if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
1565    #define _CPU_Priority_Mask( _bit_number ) \\
1566    ( 1 << (_bit_number) )
1567    #endif
1568
1569Bit Scan Support
1570================
1571
1572The ``_CPU_Priority_bits_index`` routine translates the bit numbers
1573returned by ``_CPU_Bitfield_Find_first_bit()`` into something
1574suitable for use as a major or minor component of a priority.
1575The find first bit routine may number the bits in a
1576way that is difficult to map into the major and minor components
1577of the priority.  For example, when finding the first bit set in
1578the value 0x8000, a CPU may indicate that bit 15 or 16 is set
1579based on whether the least significant bit is "zero" or "one".
1580Similarly, a CPU may only scan 32-bit values and consider the
1581most significant bit to be bit zero or one.  In this case, this
1582would be bit 16 or 17.
1583
1584This routine allows that unwieldy form to be converted
1585into a normalized form that is easier to process and use
1586as an index.
1587.. code:: c
1588
1589    #if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
1590    #define _CPU_Priority_bits_index( _priority ) \\
1591    (_priority)
1592    #endif
1593
1594.. COMMENT: COPYRIGHT (c) 1988-2002.
1595
1596.. COMMENT: On-Line Applications Research Corporation (OAR).
1597
1598.. COMMENT: All rights reserved.
1599
1600Code Tuning Parameters
1601######################
1602
1603Inline Thread_Enable_dispatch
1604=============================
1605
1606Should the calls to _Thread_Enable_dispatch be inlined?
1607
1608If TRUE, then they are inlined.
1609
1610If FALSE, then a subroutine call is made.
1611
1612Basically this is an example of the classic trade-off of size versus
1613speed.  Inlining the call (TRUE) typically increases the size of RTEMS
1614while speeding up the enabling of dispatching.
1615
1616[NOTE: In general, the _Thread_Dispatch_disable_level will only be 0 or 1
1617unless you are in an interrupt handler and that interrupt handler invokes
1618the executive.] When not inlined something calls _Thread_Enable_dispatch
1619which in turns calls _Thread_Dispatch.  If the enable dispatch is inlined,
1620then one subroutine call is avoided entirely.]
1621.. code:: c
1622
1623    #define CPU_INLINE_ENABLE_DISPATCH       FALSE
1624
1625Inline Thread_queue_Enqueue_priority
1626====================================
1627
1628Should the body of the search loops in _Thread_queue_Enqueue_priority be
1629unrolled one time?  In unrolled each iteration of the loop examines two
1630"nodes" on the chain being searched.  Otherwise, only one node is examined
1631per iteration.
1632
1633If TRUE, then the loops are unrolled.
1634
1635If FALSE, then the loops are not unrolled.
1636
1637The primary factor in making this decision is the cost of disabling and
1638enabling interrupts (_ISR_Flash) versus the cost of rest of the body of
1639the loop.  On some CPUs, the flash is more expensive than one iteration of
1640the loop body.  In this case, it might be desirable to unroll the loop.
1641It is important to note that on some CPUs, this code is the longest
1642interrupt disable period in RTEMS.  So it is necessary to strike a balance
1643when setting this parameter.
1644.. code:: c
1645
1646    #define CPU_UNROLL_ENQUEUE_PRIORITY      TRUE
1647
1648Structure Alignment Optimization
1649================================
1650
1651The following macro may be defined to the attribute setting used to force
1652alignment of critical RTEMS structures.  On some processors it may make
1653sense to have these aligned on tighter boundaries than the minimum
1654requirements of the compiler in order to have as much of the critical data
1655area as possible in a cache line.  This ensures that the first access of
1656an element in that structure fetches most, if not all, of the data
1657structure and places it in the data cache.  Modern CPUs often have cache
1658lines of at least 16 bytes and thus a single access implicitly fetches
1659some surrounding data and places that unreferenced data in the cache.
1660Taking advantage of this allows RTEMS to essentially prefetch critical
1661data elements.
1662
1663The placement of this macro in the declaration of the variables is based
1664on the syntactically requirements of the GNU C "__attribute__" extension.
1665For another toolset, the placement of this macro could be incorrect.  For
1666example with GNU C, use the following definition of
1667CPU_STRUCTURE_ALIGNMENT to force a structures to a 32 byte boundary.
1668
1669#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (32)))
1670
1671To benefit from using this, the data must be heavily used so it will stay
1672in the cache and used frequently enough in the executive to justify
1673turning this on.  NOTE:  Because of this, only the Priority Bit Map table
1674currently uses this feature.
1675
1676The following illustrates how the CPU_STRUCTURE_ALIGNMENT is defined on
1677ports which require no special alignment for optimized access to data
1678structures:
1679.. code:: c
1680
1681    #define CPU_STRUCTURE_ALIGNMENT
1682
1683Data Alignment Requirements
1684===========================
1685
1686Data Element Alignment
1687----------------------
1688
1689The CPU_ALIGNMENT macro should be set to the CPU’s worst alignment
1690requirement for data types on a byte boundary.  This is typically the
1691alignment requirement for a C double. This alignment does not take into
1692account the requirements for the stack.
1693
1694The following sets the CPU_ALIGNMENT macro to 8 which indicates that there
1695is a basic C data type for this port which much be aligned to an 8 byte
1696boundary.
1697.. code:: c
1698
1699    #define CPU_ALIGNMENT              8
1700
1701Heap Element Alignment
1702----------------------
1703
1704The CPU_HEAP_ALIGNMENT macro is set to indicate the byte alignment
1705requirement for data allocated by the RTEMS Code Heap Handler.  This
1706alignment requirement may be stricter than that for the data types
1707alignment specified by CPU_ALIGNMENT.  It is common for the heap to follow
1708the same alignment requirement as CPU_ALIGNMENT.  If the CPU_ALIGNMENT is
1709strict enough for the heap, then this should be set to CPU_ALIGNMENT. This
1710macro is necessary to ensure that allocated memory is properly aligned for
1711use by high level language routines.
1712
1713The following example illustrates how the CPU_HEAP_ALIGNMENT macro is set
1714when the required alignment for elements from the heap is the same as the
1715basic CPU alignment requirements.
1716.. code:: c
1717
1718    #define CPU_HEAP_ALIGNMENT         CPU_ALIGNMENT
1719
1720NOTE:  This does not have to be a power of 2.  It does have to be greater
1721or equal to than CPU_ALIGNMENT.
1722
1723Partition Element Alignment
1724---------------------------
1725
1726The CPU_PARTITION_ALIGNMENT macro is set to indicate the byte alignment
1727requirement for memory buffers allocated by the RTEMS Partition Manager
1728that is part of the Classic API.  This alignment requirement may be
1729stricter than that for the data types alignment specified by
1730CPU_ALIGNMENT.  It is common for the partition to follow the same
1731alignment requirement as CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict
1732enough for the partition, then this should be set to CPU_ALIGNMENT.  This
1733macro is necessary to ensure that allocated memory is properly aligned for
1734use by high level language routines.
1735
1736The following example illustrates how the CPU_PARTITION_ALIGNMENT macro is
1737set when the required alignment for elements from the RTEMS Partition
1738Manager is the same as the basic CPU alignment requirements.
1739
1740.. code:: c
1741
1742    #define CPU_PARTITION_ALIGNMENT    CPU_ALIGNMENT
1743
1744NOTE:  This does not have to be a power of 2.  It does have to be greater
1745or equal to than CPU_ALIGNMENT.
1746
1747.. COMMENT: COPYRIGHT (c) 1988-2002.
1748
1749.. COMMENT: On-Line Applications Research Corporation (OAR).
1750
1751.. COMMENT: All rights reserved.
1752
1753Miscellaneous
1754#############
1755
1756Fatal Error Default Handler
1757===========================
1758
1759The ``_CPU_Fatal_halt`` routine is the default fatal error handler. This
1760routine copies _error into a known place – typically a stack location or
1761a register, optionally disables interrupts, and halts/stops the CPU.  It
1762is prototyped as follows and is often implemented as a macro:
1763.. code:: c
1764
1765    void _CPU_Fatal_halt(
1766    unsigned32 _error
1767    );
1768
1769CPU Context Validation
1770======================
1771
1772The test case ``sptests/spcontext01`` ensures that the context switching and
1773interrupt processing works.  This test uses two support functions provided by
1774the CPU port.  These two functions are only used for this test and have no
1775other purpose.
1776.. code:: c
1777
1778    void _CPU_Context_volatile_clobber( uintptr_t pattern );
1779    void _CPU_Context_validate( uintptr_t pattern );
1780
1781The ``_CPU_Context_volatile_clobber()`` function clobbers all volatile
1782registers with values derived from the pattern parameter.  This makes sure that
1783the interrupt prologue code restores all volatile registers of the interrupted
1784context.
1785
1786The ``_CPU_Context_validate()`` function initializes and validates the CPU
1787context with values derived from the pattern parameter.  This function will not
1788return if the CPU context remains consistent.  In case this function returns
1789the CPU port is broken.  The test uses two threads which concurrently validate
1790the CPU context with a different patterns for each thread.  This ensures that
1791the context switching code works.
1792
1793Processor Endianness
1794====================
1795
1796Endianness refers to the order in which numeric values are stored in
1797memory by the microprocessor.  Big endian architectures store the most
1798significant byte of a multi-byte numeric value in the byte with the lowest
1799address.  This results in the hexadecimal value 0x12345678 being stored as
18000x12345678 with 0x12 in the byte at offset zero, 0x34 in the byte at
1801offset one, etc..  The Motorola M68K and numerous RISC processor families
1802is big endian.  Conversely, little endian architectures store the least
1803significant byte of a multi-byte numeric value in the byte with the lowest
1804address.  This results in the hexadecimal value 0x12345678 being stored as
18050x78563412 with 0x78 in the byte at offset zero, 0x56 in the byte at
1806offset one, etc..  The Intel ix86 family is little endian.
1807Interestingly, some CPU models within the PowerPC and MIPS architectures
1808can be switched between big and little endian modes.  Most embedded
1809systems use these families strictly in big endian mode.
1810
1811RTEMS must be informed of the byte ordering for this microprocessor family
1812and, optionally, endian conversion routines may be provided as part of the
1813port.  Conversion between endian formats is often necessary in
1814multiprocessor environments and sometimes needed when interfacing with
1815peripheral controllers.
1816
1817Specifying Processor Endianness
1818-------------------------------
1819
1820The ``CPU_BIG_ENDIAN`` and ``CPU_LITTLE_ENDIAN`` are
1821set to specify the endian
1822format used by this microprocessor.  These macros should not be set to the
1823same value.  The following example illustrates how these macros should be
1824set on a processor family that is big endian.
1825.. code:: c
1826
1827    #define CPU_BIG_ENDIAN                           TRUE
1828    #define CPU_LITTLE_ENDIAN                        FALSE
1829
1830The ``CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK`` macro is set to the amount of
1831stack space above the minimum thread stack space required by the MPCI
1832Receive Server Thread.  This macro is needed because in a multiprocessor
1833system the MPCI Receive Server Thread must be able to process all
1834directives.
1835.. code:: c
1836
1837    #define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
1838
1839Endian Swap Unsigned Integers
1840-----------------------------
1841
1842The port should provide routines to swap sixteen (``CPU_swap_u16``) and
1843thirty-bit (``CPU_swap_u32``) unsigned integers.  These are primarily used in
1844two areas of RTEMS - multiprocessing support and the network endian swap
1845routines.  The ``CPU_swap_u32`` routine must be implemented as a static
1846routine rather than a macro because its address is taken and used
1847indirectly.  On the other hand, the ``CPU_swap_u16`` routine may be
1848implemented as a macro.
1849
1850Some CPUs have special instructions that swap a 32-bit quantity in a
1851single instruction (e.g. i486).  It is probably best to avoid an "endian
1852swapping control bit" in the CPU.  One good reason is that interrupts
1853would probably have to be disabled to insure that an interrupt does not
1854try to access the same "chunk" with the wrong endian.  Another good reason
1855is that on some CPUs, the endian bit endianness for ALL fetches – both
1856code and data – so the code will be fetched incorrectly.
1857
1858The following is an implementation of the ``CPU_swap_u32`` routine that will
1859work on any CPU.  It operates by breaking the unsigned thirty-two bit
1860integer into four byte-wide quantities and reassemblying them.
1861.. code:: c
1862
1863    static inline unsigned int CPU_swap_u32(
1864    unsigned int value
1865    )
1866    {
1867    unsigned32 byte1, byte2, byte3, byte4, swapped;
1868    byte4 = (value >> 24) & 0xff;
1869    byte3 = (value >> 16) & 0xff;
1870    byte2 = (value >> 8)  & 0xff;
1871    byte1 =  value        & 0xff;
1872    swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
1873    return( swapped );
1874    }
1875
1876Although the above implementation is portable, it is not particularly
1877efficient.  So if there is a better way to implement this on a particular
1878CPU family or model, please do so.  The efficiency of this routine has
1879significant impact on the efficiency of the multiprocessing support code
1880in the shared memory driver and in network applications using the ntohl()
1881family of routines.
1882
1883Most microprocessor families have rotate instructions which can be used to
1884greatly improve the ``CPU_swap_u32`` routine.  The most common
1885way to do this is to:
1886.. code:: c
1887
1888    swap least significant two bytes with 16-bit rotate
1889    swap upper and lower 16-bits
1890    swap most significant two bytes with 16-bit rotate
1891
1892Some CPUs have special instructions that swap a 32-bit quantity in a
1893single instruction (e.g. i486).  It is probably best to avoid an "endian
1894swapping control bit" in the CPU.  One good reason is that interrupts
1895would probably have to be disabled to insure that an interrupt does not
1896try to access the same "chunk" with the wrong endian.  Another good reason
1897is that on some CPUs, the endian bit endianness for ALL fetches – both
1898code and data – so the code will be fetched incorrectly.
1899
1900Similarly, here is a portable implementation of the ``CPU_swap_u16``
1901routine.  Just as with the ``CPU_swap_u32`` routine, the porter
1902should provide a better implementation if possible.
1903.. code:: c
1904
1905    #define CPU_swap_u16( value ) \\
1906    (((value&0xff) << 8) | ((value >> 8)&0xff))
1907
1908Command and Variable Index
1909##########################
1910
1911There are currently no Command and Variable Index entries.
1912
1913.. COMMENT: @printindex fn
1914
1915Concept Index
1916#############
1917
1918There are currently no Concept Index entries.
1919
1920.. COMMENT: @printindex cp
Note: See TracBrowser for help on using the repository browser.