source: rtems-docs/porting/porting.rst @ 7526578

4.115
Last change on this file since 7526578 was 7526578, checked in by Amar Takhar <amar@…>, on 01/16/16 at 23:28:08

Fix markup

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