]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - doc/html/ref/hal-porting-architecture.html
Initial revision
[karo-tx-redboot.git] / doc / html / ref / hal-porting-architecture.html
1 <!-- Copyright (C) 2003 Red Hat, Inc.                                -->
2 <!-- This material may be distributed only subject to the terms      -->
3 <!-- and conditions set forth in the Open Publication License, v1.0  -->
4 <!-- or later (the latest version is presently available at          -->
5 <!-- http://www.opencontent.org/openpub/).                           -->
6 <!-- Distribution of the work or derivative of the work in any       -->
7 <!-- standard (paper) book form is prohibited unless prior           -->
8 <!-- permission is obtained from the copyright holder.               -->
9 <HTML
10 ><HEAD
11 ><TITLE
12 >Architecture HAL Porting</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
14 <META
15 NAME="GENERATOR"
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
17 "><LINK
18 REL="HOME"
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
21 REL="UP"
22 TITLE=" Porting Guide"
23 HREF="hal-porting-guide.html"><LINK
24 REL="PREVIOUS"
25 TITLE="Variant HAL Porting"
26 HREF="hal-porting-variant.html"><LINK
27 REL="NEXT"
28 TITLE="Future developments"
29 HREF="hal-future-developments.html"></HEAD
30 ><BODY
31 CLASS="SECTION"
32 BGCOLOR="#FFFFFF"
33 TEXT="#000000"
34 LINK="#0000FF"
35 VLINK="#840084"
36 ALINK="#0000FF"
37 ><DIV
38 CLASS="NAVHEADER"
39 ><TABLE
40 SUMMARY="Header navigation table"
41 WIDTH="100%"
42 BORDER="0"
43 CELLPADDING="0"
44 CELLSPACING="0"
45 ><TR
46 ><TH
47 COLSPAN="3"
48 ALIGN="center"
49 >eCos Reference Manual</TH
50 ></TR
51 ><TR
52 ><TD
53 WIDTH="10%"
54 ALIGN="left"
55 VALIGN="bottom"
56 ><A
57 HREF="hal-porting-variant.html"
58 ACCESSKEY="P"
59 >Prev</A
60 ></TD
61 ><TD
62 WIDTH="80%"
63 ALIGN="center"
64 VALIGN="bottom"
65 >Chapter 11. Porting Guide</TD
66 ><TD
67 WIDTH="10%"
68 ALIGN="right"
69 VALIGN="bottom"
70 ><A
71 HREF="hal-future-developments.html"
72 ACCESSKEY="N"
73 >Next</A
74 ></TD
75 ></TR
76 ></TABLE
77 ><HR
78 ALIGN="LEFT"
79 WIDTH="100%"></DIV
80 ><DIV
81 CLASS="SECTION"
82 ><H1
83 CLASS="SECTION"
84 ><A
85 NAME="HAL-PORTING-ARCHITECTURE">Architecture HAL Porting</H1
86 ><P
87 >A new architecture HAL is the most complex HAL to write, and it the
88 least easily described. Hence this section is presently nothing more
89 than a place holder for the future.</P
90 ><DIV
91 CLASS="SECTION"
92 ><H2
93 CLASS="SECTION"
94 ><A
95 NAME="AEN9793">HAL Architecture Porting Process</H2
96 ><P
97 >The easiest way to make a new architecture HAL is simply to copy an
98 existing architecture HAL of an, if possible, closely matching
99 architecture and change all the files to match the new
100 architecture. The MIPS architecture HAL should be used if possible, as
101 it has the appropriate layout and coding conventions. Other HALs
102 may deviate from that norm in various ways.</P
103 ><DIV
104 CLASS="NOTE"
105 ><BLOCKQUOTE
106 CLASS="NOTE"
107 ><P
108 ><B
109 >Note: </B
110 > eCos is written for GCC. It requires C and C++
111 compiler support as well as a few compiler features introduced during
112 eCos development - so compilers older than eCos may not provide these
113 features. Note that there is no C++ support for any 8 or 16 bit
114 CPUs. Before you can undertake an eCos port, you need the required
115 compiler support.</P
116 ></BLOCKQUOTE
117 ></DIV
118 ><P
119 >The following gives a rough outline of the steps needed to create a
120 new architecture HAL. The exact order and set of steps needed will
121 vary greatly from architecture to architecture, so a lot of
122 flexibility is required. And of course, if the architecture HAL is to
123 be tested, it is necessary to do variant and  platform ports for the
124 initial target simultaneously.</P
125 ><P
126 ></P
127 ><OL
128 TYPE="1"
129 ><LI
130 ><P
131 >Make a new directory for the new architecture under the
132 <TT
133 CLASS="FILENAME"
134 >hal</TT
135 > directory in the source repository. Make an
136 <TT
137 CLASS="FILENAME"
138 >arch</TT
139 > directory under this and populate this with
140 the standard set of package directories.</P
141 ></LI
142 ><LI
143 ><P
144 >Copy the CDL file from an example HAL changing its name to match the
145 new HAL. Edit the file, changing option names as appropriate. Delete
146 any options that are specific to the original HAL, and and any new
147 options that are necessary for the new architecture. This is likely to
148 be a continuing process during the development of the HAL. See <A
149 HREF="hal-porting-architecture.html#HAL-PORTING-ARCHITECTURE-CDL"
150 >the Section called <I
151 >CDL Requirements</I
152 ></A
153 > for more details.</P
154 ></LI
155 ><LI
156 ><P
157 >Copy the <TT
158 CLASS="FILENAME"
159 >hal_arch.h</TT
160 > file from an example
161 HAL. Within this file you need to change or define the following:</P
162 ><P
163 ></P
164 ><UL
165 ><LI
166 ><P
167 >Define the <SPAN
168 CLASS="STRUCTNAME"
169 >HAL_SavedRegisters</SPAN
170 > structure. This
171 may need to reflect the save order of any group register save/restore
172 instructions, the interrupt and exception save and restore formats,
173 and the procedure calling conventions. It may also need to cater for
174 optional FPUs and other functional units. It can be quite difficult to
175 develop a layout that copes with all requirements.</P
176 ></LI
177 ><LI
178 ><P
179 >Define the bit manipulation routines,
180 <TT
181 CLASS="LITERAL"
182 >HAL_LSBIT_INDEX()</TT
183 > and
184 <TT
185 CLASS="LITERAL"
186 >HAL_MSBIT_INDEX()</TT
187 >. If the architecture contains
188 instructions to perform these, or related, operations, then these
189 should be defined as inline assembler fragments. Otherwise make them
190 calls to functions.</P
191 ></LI
192 ><LI
193 ><P
194 >Define <TT
195 CLASS="LITERAL"
196 >HAL_THREAD_INIT_CONTEXT()</TT
197 >. This initializes
198 a restorable CPU context onto a stack pointer so that a later call to
199 <TT
200 CLASS="LITERAL"
201 >HAL_THREAD_LOAD_CONTEXT()</TT
202 > or
203 <TT
204 CLASS="LITERAL"
205 >HAL_THREAD_SWITCH_CONTEXT()</TT
206 > will execute it
207 correctly. This macro needs to take account of the same optional
208 features of the architecture as the definition of
209 <SPAN
210 CLASS="STRUCTNAME"
211 >HAL_SavedRegisters</SPAN
212 >.</P
213 ></LI
214 ><LI
215 ><P
216 >Define <TT
217 CLASS="LITERAL"
218 >HAL_THREAD_LOAD_CONTEXT()</TT
219 > and
220 <TT
221 CLASS="LITERAL"
222 >HAL_THREAD_SWITCH_CONTEXT()</TT
223 >. These should just be
224 calls to functions in <TT
225 CLASS="FILENAME"
226 >context.S</TT
227 >.</P
228 ></LI
229 ><LI
230 ><P
231 >Define <TT
232 CLASS="LITERAL"
233 >HAL_REORDER_BARRIER()</TT
234 >. This prevents code
235 being moved by the compiler and is necessary in some order-sensitive
236 code. This macro is actually defined identically in all architecture,
237 so it can just be copied.</P
238 ></LI
239 ><LI
240 ><P
241 >Define breakpoint support. The macro
242 <TT
243 CLASS="LITERAL"
244 >HAL_BREAKPOINT(label)</TT
245 > needs to be an inline assembly
246 fragment that invokes a breakpoint. The breakpoint instruction should
247 be labeled with the <TT
248 CLASS="PARAMETER"
249 ><I
250 >label</I
251 ></TT
252 >
253 argument. <TT
254 CLASS="LITERAL"
255 >HAL_BREAKINST</TT
256 > and
257 <TT
258 CLASS="LITERAL"
259 >HAL_BREAKINST_SIZE</TT
260 > define the breakpoint
261 instruction for debugging purposes.</P
262 ></LI
263 ><LI
264 ><P
265 >Define GDB support. GDB views the registers of the target as a linear
266 array, with each register having a well defined offset. This array may
267 differ from the ordering defined in
268 <SPAN
269 CLASS="STRUCTNAME"
270 >HAL_SavedRegisters</SPAN
271 >. The macros
272 <TT
273 CLASS="LITERAL"
274 >HAL_GET_GDB_REGISTERS()</TT
275 > and
276 <TT
277 CLASS="LITERAL"
278 >HAL_SET_GDB_REGISTERS()</TT
279 > translate between the GDB
280 array and the <SPAN
281 CLASS="STRUCTNAME"
282 >HAL_SavedRegisters</SPAN
283 > structure.
284 The <TT
285 CLASS="LITERAL"
286 >HAL_THREAD_GET_SAVED_REGISTERS()</TT
287 > translates a
288 stack pointer saved by the context switch macros into a pointer to a
289 <SPAN
290 CLASS="STRUCTNAME"
291 >HAL_SavedRegisters</SPAN
292 > structure. Usually this is
293 a one-to-one translation, but this macro allows it to differ if
294 necessary.</P
295 ></LI
296 ><LI
297 ><P
298 >Define long jump support. The type <SPAN
299 CLASS="TYPE"
300 >hal_jmp_buf</SPAN
301 > and the
302 functions <TT
303 CLASS="FUNCTION"
304 >hal_setjmp()</TT
305 > and
306 <TT
307 CLASS="LITERAL"
308 >hal_longjmp()</TT
309 > provide the underlying implementation
310 of the C library <TT
311 CLASS="FUNCTION"
312 >setjmp()</TT
313 > and
314 <TT
315 CLASS="FUNCTION"
316 >longjmp()</TT
317 >.</P
318 ></LI
319 ><LI
320 ><P
321 >Define idle thread action. Generally the macro
322 <TT
323 CLASS="LITERAL"
324 >HAL_IDLE_THREAD_ACTION()</TT
325 > is defined to call a
326 function in <TT
327 CLASS="FILENAME"
328 >hal_misc.c</TT
329 >.</P
330 ></LI
331 ><LI
332 ><P
333 >Define stack sizes. The macros
334 <TT
335 CLASS="LITERAL"
336 >CYGNUM_HAL_STACK_SIZE_MINIMUM</TT
337 > and
338 <TT
339 CLASS="LITERAL"
340 >CYGNUM_HAL_STACK_SIZE_TYPICAL</TT
341 > should be defined to
342 the minimum size for any thread stack and a reasonable default for
343 most threads respectively. It is usually best to construct these out
344 of component sizes for the CPU save state and procedure call stack
345 usage. These definitions should not use anything other than numerical
346 values since they can be used from assembly code in some HALs.</P
347 ></LI
348 ><LI
349 ><P
350 >Define memory access macros. These macros provide translation between
351 cached and uncached and physical memory spaces. They usually consist
352 of masking out bits of the supplied address and ORing in alternative
353 address bits.</P
354 ></LI
355 ><LI
356 ><P
357 >Define global pointer save/restore macros. These really only need
358 defining if the calling conventions of the architecture require a
359 global pointer (as does the MIPS architecture), they may be empty
360 otherwise. If it is necessary to define these, then take a look at the
361 MIPS implementation for an example.</P
362 ></LI
363 ></UL
364 ></LI
365 ><LI
366 ><P
367 >Copy <TT
368 CLASS="FILENAME"
369 >hal_intr.h</TT
370 > from an example HAL. Within this
371 file you should change or define the following:</P
372 ><P
373 ></P
374 ><UL
375 ><LI
376 ><P
377 >Define the exception vectors. These should be detailed in the
378 architecture specification. Essentially for each exception entry point
379 defined by the architecture there should be an entry in the VSR
380 table. The offsets of these VSR table entries should be defined here
381 by <TT
382 CLASS="LITERAL"
383 >CYGNUM_HAL_VECTOR_*</TT
384 > definitions. The size of the
385 VSR table also needs to be defined here.</P
386 ></LI
387 ><LI
388 ><P
389 >Map any hardware exceptions to standard names. There is a group of
390 exception vector name of the form
391 <TT
392 CLASS="LITERAL"
393 >CYGNUM_HAL_EXCEPTION_*</TT
394 > that define a wide variety
395 of possible exceptions that many architectures raise. Generic code
396 detects whether the architecture can raise a given exception by
397 testing whether a given <TT
398 CLASS="LITERAL"
399 >CYGNUM_HAL_EXCEPTION_*</TT
400 >
401 definition is present. If it is present then its value is the vector
402 that raises that exception. This does not need to be a one-to-one
403 correspondence, and several <TT
404 CLASS="LITERAL"
405 >CYGNUM_HAL_EXCEPTION_*</TT
406 >
407 definitions may have the same value.</P
408 ><P
409 >Interrupt vectors are usually defined in the variant or platform
410 HALs. The interrupt number space may either be continuous with the VSR
411 number space, where they share a vector table (as in the i386) or may
412 be a separate space where a separate decode stage is used (as in MIPS
413 or PowerPC).</P
414 ></LI
415 ><LI
416 ><P
417 >Declare any static data used by the HAL to handle interrupts and
418 exceptions. This is usually three vectors for interrupts:
419 <TT
420 CLASS="LITERAL"
421 >hal_interrupt_handlers[]</TT
422 >,
423 <TT
424 CLASS="LITERAL"
425 >hal_interrupt_data[]</TT
426 > and
427 <TT
428 CLASS="LITERAL"
429 >hal_interrupt_objects[]</TT
430 >, which are sized according
431 to the interrupt vector definitions. In addition a definition for the
432 VSR table, <TT
433 CLASS="LITERAL"
434 >hal_vsr_table[]</TT
435 > should be made. These
436 vectors are normally defined in either <TT
437 CLASS="FILENAME"
438 >vectors.S</TT
439 >
440 or <TT
441 CLASS="FILENAME"
442 >hal_misc.c</TT
443 >.</P
444 ></LI
445 ><LI
446 ><P
447 >Define interrupt enable/disable macros. These are normally inline
448 assembly fragments to execute the instructions, or manipulate the CPU
449 register, that contains the CPU interrupt enable bit.</P
450 ></LI
451 ><LI
452 ><P
453 >A feature that many HALs support is the ability to execute DSRs on the
454 interrupt stack. This is not an essential feature, and is better left
455 unimplemented in the initial porting effort. If this is required, then
456 the macro <TT
457 CLASS="LITERAL"
458 >HAL_INTERRUPT_STACK_CALL_PENDING_DSRS()</TT
459 >
460 should be defined to call a function in
461 <TT
462 CLASS="FILENAME"
463 >vectors.S</TT
464 >.</P
465 ></LI
466 ><LI
467 ><P
468 >Define the interrupt and VSR attachment macros. If the same arrays as
469 for other HALs have been used for VSR and interrupt vectors, then
470 these macro can be copied across unchanged.</P
471 ></LI
472 ></UL
473 ></LI
474 ><LI
475 ><P
476 >A number of other header files also need to be filled in:</P
477 ><P
478 ></P
479 ><UL
480 ><LI
481 ><P
482 ><TT
483 CLASS="FILENAME"
484 >basetype.h</TT
485 >. This file defines the basic types
486 used by eCos, together with the endianness and some other
487 characteristics. This file only really needs to contain definitions
488 if the architecture differs significantly from the defaults defined
489 in <TT
490 CLASS="FILENAME"
491 >cyg_type.h</TT
492 ></P
493 ></LI
494 ><LI
495 ><P
496 ><TT
497 CLASS="FILENAME"
498 >hal_io.h</TT
499 >. This file contains macros for accessing
500 device IO registers. If the architecture uses memory mapped IO, then
501 these can be copied unchanged from an existing HAL such as MIPS. If
502 the architecture uses special IO instructions, then these macros must
503 be defined as inline assembler fragments. See the I386 HAL for an
504 example. PCI bus access macros are usually defined in the variant or
505 platform HALs.</P
506 ></LI
507 ><LI
508 ><P
509 ><TT
510 CLASS="FILENAME"
511 >hal_cache.h</TT
512 >. This file contains cache access
513 macros. If the architecture defines cache instructions, or control
514 registers, then the access macros should be defined here. Otherwise
515 they must be defined in the variant or platform HAL. Usually the cache
516 dimensions (total size, line size, ways etc.) are defined in the
517 variant HAL.</P
518 ></LI
519 ><LI
520 ><P
521 ><TT
522 CLASS="FILENAME"
523 >arch.inc</TT
524 > and
525 <TT
526 CLASS="FILENAME"
527 >&lt;architecture&gt;.inc</TT
528 >. These files are
529 assembler headers used by <TT
530 CLASS="FILENAME"
531 >vectors.S</TT
532 > and
533 <TT
534 CLASS="FILENAME"
535 >context.S</TT
536 >.
537 <TT
538 CLASS="FILENAME"
539 >&lt;architecture&gt;.inc</TT
540 > is a general purpose
541 header that should contain things like register aliases, ABI
542 definitions and macros useful to general assembly
543 code. If there are no such definitions, then this file need not be
544 provided. <TT
545 CLASS="FILENAME"
546 >arch.inc</TT
547 > contains macros for performing
548 various eCos related operations such as initializing the CPU, caches,
549 FPU etc. The definitions here may often be configured or overridden by
550 definitions in the variant or platform HALs. See the MIPS HAL for an
551 example of this.</P
552 ></LI
553 ></UL
554 ></LI
555 ><LI
556 ><P
557 >Write <TT
558 CLASS="FILENAME"
559 >vectors.S</TT
560 >. This is the most important file
561 in the HAL. It contains the CPU initialization code, exception and
562 interrupt handlers. While other HALs should be consulted for
563 structures and techniques, there is very little here that can be
564 copied over without major edits.</P
565 ><P
566 >The main pieces of code that need to be defined here are:</P
567 ><P
568 ></P
569 ><UL
570 ><LI
571 ><P
572 >Reset vector. This usually need to be positioned at the start of the
573 ROM or FLASH, so should be in a linker section of its own. It can then be
574 placed correctly by the linker script. Normally this code is little
575 more than a jump to the label <TT
576 CLASS="LITERAL"
577 >_start</TT
578 >.</P
579 ></LI
580 ><LI
581 ><P
582 >Exception vectors. These are the trampoline routines connected to the
583 hardware exception entry points that vector through the VSR table. In
584 many architectures these are adjacent to the reset vector, and should
585 occupy the same linker section. If the architecture allow the vectors
586 to be moved then it may be necessary for these trampolines to be
587 position independent so they can be relocated at runtime.</P
588 ><P
589 >The trampolines should do the minimum necessary to transfer control
590 from the hardware vector to the VSR pointed to by the matching table
591 entry. Exactly how this is done depends on the architecture. Usually
592 the trampoline needs to get some working registers by either saving
593 them to CPU special registers (e.g. PowerPC SPRs), using reserved
594 general registers (MIPS K0 and K1), using only memory based
595 operations (IA32), or just jumping directly (ARM). The VSR table index
596 to be used is either implicit in the entry point taken (PowerPC, IA32,
597 ARM), or must be determined from a CPU register (MIPS).</P
598 ></LI
599 ><LI
600 ><P
601 >Write kernel startup code. This is the location the reset vector jumps
602 to, and can be in the main text section of the executable, rather than
603 a special section. The code here should first initialize the CPU and other
604 hardware subsystems. The best approach is to use a set of macro
605 calls that are defined either in <TT
606 CLASS="FILENAME"
607 >arch.inc</TT
608 > or
609 overridden in the variant or platform HALs. Other jobs that this code
610 should do are: initialize stack pointer; copy the data section from
611 ROM to RAM if necessary; zero the BSS; call variant and platform
612 initializers; call <TT
613 CLASS="FUNCTION"
614 >cyg_hal_invoke_constructors()</TT
615 >;
616 call <TT
617 CLASS="FUNCTION"
618 >initialize_stub()</TT
619 > if necessary. Finally it
620 should call <TT
621 CLASS="FUNCTION"
622 >cyg_start()</TT
623 >. See <A
624 HREF="hal-exception-handling.html#HAL-STARTUP"
625 >the Section called <I
626 >HAL Startup</I
627 > in Chapter 10</A
628 > for details.</P
629 ></LI
630 ><LI
631 ><P
632 >Write the default exception VSR. This VSR is installed in the VSR
633 table for all synchronous exception vectors. See <A
634 HREF="hal-default-synchronous-exception-handling.html"
635 >the Section called <I
636 >Default Synchronous Exception Handling</I
637 > in Chapter 10</A
638 > for details of
639 what this VSR does.</P
640 ></LI
641 ><LI
642 ><P
643 >Write the default interrupt VSR. This is installed in all VSR table
644 entries that correspond to external interrupts. See <A
645 HREF="hal-default-synchronous-exception-handling.html"
646 >the Section called <I
647 >Default Synchronous Exception Handling</I
648 > in Chapter 10</A
649 > for details of
650 what this VSR does.</P
651 ></LI
652 ><LI
653 ><P
654 >Write
655 <TT
656 CLASS="FUNCTION"
657 >hal_interrupt_stack_call_pending_dsrs()</TT
658 >. If this
659 function is defined in <TT
660 CLASS="FILENAME"
661 >hal_arch.h</TT
662 > then it should
663 appear here. The purpose of this function is to call DSRs on the
664 interrupt stack rather than the current thread's stack. This is not an
665 essential feature, and may be left until later. However it interacts
666 with the stack switching that goes on in the interrupt VSR, so it may
667 make sense to write these pieces of code at the same time to ensure
668 consistency.</P
669 ><P
670 >When this function is implemented it should do the following:</P
671 ><P
672 ></P
673 ><UL
674 ><LI
675 ><P
676 >Take a copy of the current SP and then switch to the interrupt stack.</P
677 ></LI
678 ><LI
679 ><P
680 >Save the old SP, together with the CPU status register (or whatever
681 register contains the interrupt enable status) and any other
682 registers that may be corrupted by a function call (such as any link
683 register) to locations in the interrupt stack.</P
684 ></LI
685 ><LI
686 ><P
687 >Enable interrupts.</P
688 ></LI
689 ><LI
690 ><P
691 >Call <TT
692 CLASS="FUNCTION"
693 >cyg_interrupt_call_pending_DSRs()</TT
694 >. This is a
695 kernel functions that actually calls any pending DSRs.</P
696 ></LI
697 ><LI
698 ><P
699 >Retrieve saved registers from the interrupt stack and switch back to
700 the current thread stack.</P
701 ></LI
702 ><LI
703 ><P
704 >Merge the interrupt enable state recorded in the save CPU status
705 register with the current value of the status register to restore the
706 previous enable state. If the status register does not contain any
707 other persistent state then this can be a simple restore of the
708 register. However if the register contains other state bits that might
709 have been changed by a DSR, then care must be taken not to disturb
710 these.</P
711 ></LI
712 ></UL
713 ></LI
714 ><LI
715 ><P
716 >Define any data items needed. Typically <TT
717 CLASS="FILENAME"
718 >vectors.S</TT
719 >
720 may contain definitions for the VSR table, the interrupt tables and the
721 interrupt stack. Sometimes these are only default definitions that may
722 be overridden by the variant or platform HALs.</P
723 ></LI
724 ></UL
725 ></LI
726 ><LI
727 ><P
728 >Write <TT
729 CLASS="FILENAME"
730 >context.S</TT
731 >. This file contains the context
732 switch code. See <A
733 HREF="hal-architecture-characterization.html#HAL-CONTEXT-SWITCH"
734 >the Section called <I
735 >Thread Context Switching</I
736 > in Chapter 9</A
737 > for details of
738 how these functions operate. This file may also contain the
739 implementation of <TT
740 CLASS="FUNCTION"
741 >hal_setjmp()</TT
742 > and
743 <TT
744 CLASS="FUNCTION"
745 >hal_longjmp()</TT
746 >.</P
747 ></LI
748 ><LI
749 ><P
750 >Write <TT
751 CLASS="FILENAME"
752 >hal_misc.c</TT
753 >. This file contains any C
754 data and functions needed by the HAL. These might include:</P
755 ><P
756 ></P
757 ><UL
758 ><LI
759 ><P
760 ><TT
761 CLASS="VARNAME"
762 >hal_interrupt_*[]</TT
763 >. In some HALs, if these arrays
764 are not defined in <TT
765 CLASS="FILENAME"
766 >vectors.S</TT
767 > then they must be
768 defined here.</P
769 ></LI
770 ><LI
771 ><P
772 ><TT
773 CLASS="FUNCTION"
774 >cyg_hal_exception_handler()</TT
775 >. This function is
776 called from the exception VSR. It usually does extra decoding of the
777 exception and invokes any special handlers for things like FPU traps,
778 bus errors or memory exceptions. If there is nothing special to be
779 done for an exception, then it either calls into the GDB stubs, by
780 calling <TT
781 CLASS="FUNCTION"
782 >__handle_exception()</TT
783 >, or
784 invokes the kernel by calling
785 <TT
786 CLASS="FUNCTION"
787 >cyg_hal_deliver_exception()</TT
788 >.</P
789 ></LI
790 ><LI
791 ><P
792 ><TT
793 CLASS="FUNCTION"
794 >hal_arch_default_isr()</TT
795 >. The
796 <TT
797 CLASS="VARNAME"
798 >hal_interrupt_handlers[]</TT
799 > array is usually
800 initialized with pointers to <TT
801 CLASS="FILENAME"
802 >hal_default_isr()</TT
803 >,
804 which is defined in the common HAL. This function handles things like
805 Ctrl-C processing, but if that is not relevant, then it will call
806 <TT
807 CLASS="FUNCTION"
808 >hal_arch_default_isr()</TT
809 >. Normally this function
810 should just return zero.</P
811 ></LI
812 ><LI
813 ><P
814 ><TT
815 CLASS="FUNCTION"
816 >cyg_hal_invoke_constructors()</TT
817 >. This calls the
818 constructors for all static objects before the program starts. eCos
819 relies on these being called in the correct order for it to function
820 correctly. The exact way in which constructors are handled may differ
821 between architectures, although most use a simple table of function
822 pointers between labels <TT
823 CLASS="LITERAL"
824 >__CTOR_LIST__</TT
825 > and
826 <TT
827 CLASS="LITERAL"
828 >__CTOR_END__</TT
829 > which must called in order from the
830 top down. Generally, this function can be copied directly from an
831 existing architecture HAL.</P
832 ></LI
833 ><LI
834 ><P
835 >Bit indexing functions. If the macros
836 <TT
837 CLASS="LITERAL"
838 >HAL_LSBIT_INDEX()</TT
839 > and
840 <TT
841 CLASS="LITERAL"
842 >HAL_MSBIT_INDEX()</TT
843 > are defined as function calls,
844 then the functions should appear here. The main reason for doing this
845 is that the architecture does not have support for bit indexing and
846 these functions must provide the functionality by conventional
847 means. While the trivial implementation is a simple for loop, it is
848 expensive and non-deterministic. Better, constant time,
849 implementations can be found in several HALs (MIPS for example).</P
850 ></LI
851 ><LI
852 ><P
853 ><TT
854 CLASS="FUNCTION"
855 >hal_delay_us()</TT
856 >. If the macro
857 <TT
858 CLASS="LITERAL"
859 >HAL_DELAY_US()</TT
860 > is defined in <TT
861 CLASS="FILENAME"
862 >hal_intr.h</TT
863 > then it should be defined to
864 call this function. While most of the time this function is called
865 with very small values, occasionally (particularly in some ethernet
866 drivers) it is called with values of several seconds. Hence the
867 function should take care to avoid overflow in any calculations.</P
868 ></LI
869 ><LI
870 ><P
871 ><TT
872 CLASS="FUNCTION"
873 >hal_idle_thread_action()</TT
874 >. This function is called
875 from the idle thread via the
876 <TT
877 CLASS="LITERAL"
878 >HAL_IDLE_THREAD_ACTION()</TT
879 > macro, if so
880 defined. While normally this function does nothing, during development
881 this is often a good place to report various important system
882 parameters on LCDs, LED or other displays. This function can also
883 monitor system state and report any anomalies. If the architecture
884 supports a <TT
885 CLASS="LITERAL"
886 >halt</TT
887 > instruction then this is a good
888 place to put an inline assembly fragment to execute it. It is also a
889 good place to handle any power saving activity.</P
890 ></LI
891 ></UL
892 ></LI
893 ><LI
894 ><P
895 >Create the <TT
896 CLASS="FILENAME"
897 >&lt;architecture&gt;.ld</TT
898 > file. While
899 this file may need to be moved to the variant HAL in the future, it
900 should initially be defined here, and only moved if necessary.</P
901 ><P
902 >This file defines a set of macros that are used by the platform
903 <TT
904 CLASS="LITERAL"
905 >.ldi</TT
906 > files to generate linker scripts. Most GCC
907 toolchains are very similar so the correct approach is to copy the
908 file from an existing architecture and edit it. The main things that
909 will need editing are the <TT
910 CLASS="LITERAL"
911 >OUTPUT_FORMAT()</TT
912 > directive
913 and maybe the creation or allocation of extra sections to various
914 macros. Running the target linker with just the
915 <TT
916 CLASS="LITERAL"
917 >--verbose</TT
918 > argument will cause it to output its
919 default linker script. This can be compared with the
920 <TT
921 CLASS="LITERAL"
922 >.ld</TT
923 > file and appropriate edits made.</P
924 ></LI
925 ><LI
926 ><P
927 >If GDB stubs are to be supported in RedBoot or eCos, then support must
928 be included for these. The most important of these are <TT
929 CLASS="FILENAME"
930 >include/&lt;architecture&gt;-stub.h</TT
931 > and
932 <TT
933 CLASS="FILENAME"
934 >src/&lt;architecture&gt;-stub.c</TT
935 >. In all existing
936 architecture HALs these files, and any support files they need, have
937 been derived from files supplied in <TT
938 CLASS="LITERAL"
939 >libgloss</TT
940 >, as
941 part of the GDB toolchain package. If this is a totally new
942 architecture, this may not have been done, and they must be created
943 from scratch.</P
944 ><P
945 ><TT
946 CLASS="FILENAME"
947 >include/&lt;architecture&gt;-stub.h</TT
948 >
949 contains definitions that are used by the GDB stubs to describe the
950 size, type, number and names of CPU registers. This information is
951 usually found in the GDB support files for the architecture. It also
952 contains prototypes for the functions exported by
953 <TT
954 CLASS="FILENAME"
955 >src/&lt;architecture&gt;-stub.c</TT
956 >; however, since
957 this is common to all architectures, it can be copied from some other
958 HAL.</P
959 ><P
960 ><TT
961 CLASS="FILENAME"
962 >src/&lt;architecture&gt;-stub.c</TT
963 > implements the
964 functions exported by the header. Most of this is fairly straight
965 forward: the implementation in existing HALs should show exactly what
966 needs to be done. The only complex part is the support for
967 single-stepping. This is used a lot by GDB, so it cannot be
968 avoided. If the architecture has support for a trace or single-step
969 trap then that can be used for this purpose. If it does not then this
970 must be simulated by planting a breakpoint in the next
971 instruction. This can be quite involved since it requires some
972 analysis of the current instruction plus the state of the CPU to
973 determine where execution is going to go next.</P
974 ></LI
975 ></OL
976 ></DIV
977 ><DIV
978 CLASS="SECTION"
979 ><H2
980 CLASS="SECTION"
981 ><A
982 NAME="HAL-PORTING-ARCHITECTURE-CDL">CDL Requirements</H2
983 ><P
984 >The CDL needed for any particular architecture HAL depends to a large
985 extent on the needs of that architecture. This includes issues such as
986 support for different variants, use of FPUs, MMUs and caches. The
987 exact split between the architecture, variant and platform HALs for
988 various features is also somewhat fluid. </P
989 ><P
990 >To give a rough idea about how the CDL for an architecture is
991 structured, we will take as an example the I386 CDL.</P
992 ><P
993 >This first section introduces the CDL package and placed it under the
994 main HAL package. Include files from this package will be put in the
995 <TT
996 CLASS="FILENAME"
997 >include/cyg/hal</TT
998 > directory, and definitions from
999 this file will be placed in
1000 <TT
1001 CLASS="FILENAME"
1002 >include/pkgconf/hal_i386.h</TT
1003 >. The
1004 <TT
1005 CLASS="LITERAL"
1006 >compile</TT
1007 > line specifies the files in the
1008 <TT
1009 CLASS="FILENAME"
1010 >src</TT
1011 > directory that are to be compiled as part of
1012 this package.</P
1013 ><TABLE
1014 BORDER="5"
1015 BGCOLOR="#E0E0F0"
1016 WIDTH="70%"
1017 ><TR
1018 ><TD
1019 ><PRE
1020 CLASS="PROGRAMLISTING"
1021 >cdl_package CYGPKG_HAL_I386 {
1022     display       "i386 architecture"
1023     parent        CYGPKG_HAL
1024     hardware
1025     include_dir   cyg/hal
1026     define_header hal_i386.h
1027     description   "
1028         The i386 architecture HAL package provides generic
1029         support for this processor architecture. It is also
1030         necessary to select a specific target platform HAL
1031         package."
1032
1033     compile       hal_misc.c context.S i386_stub.c hal_syscall.c</PRE
1034 ></TD
1035 ></TR
1036 ></TABLE
1037 ><P
1038 >Next we need to generate some files using non-standard make rules. The
1039 first is <TT
1040 CLASS="FILENAME"
1041 >vectors.S</TT
1042 >, which is not put into the
1043 library, but linked explicitly with all applications. The second is
1044 the generation of the <TT
1045 CLASS="FILENAME"
1046 >target.ld</TT
1047 > file from
1048 <TT
1049 CLASS="FILENAME"
1050 >i386.ld</TT
1051 > and the startup-selected
1052 <TT
1053 CLASS="FILENAME"
1054 >.ldi</TT
1055 > file. Both of these are essentially
1056 boilerplate code that can be copied and edited.</P
1057 ><TABLE
1058 BORDER="5"
1059 BGCOLOR="#E0E0F0"
1060 WIDTH="70%"
1061 ><TR
1062 ><TD
1063 ><PRE
1064 CLASS="PROGRAMLISTING"
1065 >&#13;    make {
1066         &lt;PREFIX&gt;/lib/vectors.o : &lt;PACKAGE&gt;/src/vectors.S
1067         $(CC) -Wp,-MD,vectors.tmp $(INCLUDE_PATH) $(CFLAGS) -c -o $@ $&lt;
1068         @echo $@ ": \\" &gt; $(notdir $@).deps
1069         @tail +2 vectors.tmp &gt;&gt; $(notdir $@).deps
1070         @echo &gt;&gt; $(notdir $@).deps
1071         @rm vectors.tmp
1072     }
1073
1074     make {
1075         &lt;PREFIX&gt;/lib/target.ld: &lt;PACKAGE&gt;/src/i386.ld
1076         $(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(CFLAGS) -o $@ $&lt;
1077         @echo $@ ": \\" &gt; $(notdir $@).deps
1078         @tail +2 target.tmp &gt;&gt; $(notdir $@).deps
1079         @echo &gt;&gt; $(notdir $@).deps
1080         @rm target.tmp
1081     }</PRE
1082 ></TD
1083 ></TR
1084 ></TABLE
1085 ><P
1086 >The i386 is currently the only architecture that supports SMP. The
1087 following CDL simply enabled the HAL SMP support if
1088 required. Generally this will get enabled as a result of a
1089 <TT
1090 CLASS="LITERAL"
1091 >requires</TT
1092 > statement in the kernel. The
1093 <TT
1094 CLASS="LITERAL"
1095 >requires</TT
1096 > statement here turns off lazy FPU
1097 switching in the FPU support code, since it is inconsistent with SMP
1098 operation.</P
1099 ><TABLE
1100 BORDER="5"
1101 BGCOLOR="#E0E0F0"
1102 WIDTH="70%"
1103 ><TR
1104 ><TD
1105 ><PRE
1106 CLASS="PROGRAMLISTING"
1107 >&#13;    cdl_component CYGPKG_HAL_SMP_SUPPORT {
1108         display       "SMP support"
1109         default_value 0
1110         requires { CYGHWR_HAL_I386_FPU_SWITCH_LAZY == 0 }
1111         
1112         cdl_option CYGPKG_HAL_SMP_CPU_MAX {
1113             display       "Max number of CPUs supported"
1114             flavor        data
1115             default_value 2
1116         }
1117     }</PRE
1118 ></TD
1119 ></TR
1120 ></TABLE
1121 ><P
1122 >The i386 HAL has optional FPU support, which is enabled by default. It
1123 can be disabled to improve system performance. There are two FPU
1124 support options: either to save and restore the FPU state on every
1125 context switch, or to only switch the FPU state when necessary.</P
1126 ><TABLE
1127 BORDER="5"
1128 BGCOLOR="#E0E0F0"
1129 WIDTH="70%"
1130 ><TR
1131 ><TD
1132 ><PRE
1133 CLASS="PROGRAMLISTING"
1134 >        
1135     cdl_component CYGHWR_HAL_I386_FPU {
1136         display       "Enable I386 FPU support"
1137         default_value 1
1138         description   "This component enables support for the
1139                       I386 floating point unit."
1140
1141         cdl_option CYGHWR_HAL_I386_FPU_SWITCH_LAZY {
1142             display       "Use lazy FPU state switching"
1143             flavor        bool
1144             default_value 1
1145
1146             description "
1147                         This option enables lazy FPU state switching.
1148                         The default behaviour for eCos is to save and
1149                         restore FPU state on every thread switch, interrupt
1150                         and exception. While simple and deterministic, this
1151                         approach can be expensive if the FPU is not used by
1152                         all threads. The alternative, enabled by this option,
1153                         is to use hardware features that allow the FPU state
1154                         of a thread to be left in the FPU after it has been
1155                         descheduled, and to allow the state to be switched to
1156                         a new thread only if it actually uses the FPU. Where
1157                         only one or two threads use the FPU this can avoid a
1158                         lot of unnecessary state switching."
1159         }
1160     }</PRE
1161 ></TD
1162 ></TR
1163 ></TABLE
1164 ><P
1165 >The i386 HAL also has support for different classes of CPU. In
1166 particular, Pentium class CPUs have extra functional units, and some
1167 variants of GDB expect more registers to be reported. These options
1168 enable these features. Generally these are enabled by
1169 <TT
1170 CLASS="LITERAL"
1171 >requires</TT
1172 > statements in variant or platform
1173 packages, or in <TT
1174 CLASS="LITERAL"
1175 >.ecm</TT
1176 > files.</P
1177 ><TABLE
1178 BORDER="5"
1179 BGCOLOR="#E0E0F0"
1180 WIDTH="70%"
1181 ><TR
1182 ><TD
1183 ><PRE
1184 CLASS="PROGRAMLISTING"
1185 >&#13;    cdl_component CYGHWR_HAL_I386_PENTIUM {
1186         display       "Enable Pentium class CPU features"
1187         default_value 0
1188         description   "This component enables support for various
1189                       features of Pentium class CPUs."
1190
1191         cdl_option CYGHWR_HAL_I386_PENTIUM_SSE {
1192             display       "Save/Restore SSE registers on context switch"
1193             flavor        bool
1194             default_value 0
1195
1196             description "
1197                         This option enables SSE state switching. The default
1198                         behaviour for eCos is to ignore the SSE registers.
1199                         Enabling this option adds SSE state information to
1200                         every thread context."
1201         }
1202
1203         cdl_option CYGHWR_HAL_I386_PENTIUM_GDB_REGS {
1204             display       "Support extra Pentium registers in GDB stub"
1205             flavor        bool
1206             default_value 0
1207
1208             description "
1209                         This option enables support for extra Pentium registers
1210                         in the GDB stub. These are registers such as CR0-CR4, and
1211                         all MSRs. Not all GDBs support these registers, so the
1212                         default behaviour for eCos is to not include them in the
1213                         GDB stub support code."
1214         }
1215     }</PRE
1216 ></TD
1217 ></TR
1218 ></TABLE
1219 ><P
1220 >In the i386 HALs, the linker script is provided by the architecture
1221 HAL. In other HALs, for example MIPS, it is provided in the variant
1222 HAL. The following option provides the name of the linker script to
1223 other elements in the configuration system.</P
1224 ><TABLE
1225 BORDER="5"
1226 BGCOLOR="#E0E0F0"
1227 WIDTH="70%"
1228 ><TR
1229 ><TD
1230 ><PRE
1231 CLASS="PROGRAMLISTING"
1232 >    cdl_option CYGBLD_LINKER_SCRIPT {
1233         display "Linker script"
1234         flavor data
1235         no_define
1236         calculated  { "src/i386.ld" }
1237     }</PRE
1238 ></TD
1239 ></TR
1240 ></TABLE
1241 ><P
1242 >Finally, this interface indicates whether the platform supplied an
1243 implementation of the
1244 <TT
1245 CLASS="FUNCTION"
1246 >hal_i386_mem_real_region_top()</TT
1247 > function. If it
1248 does then it will contain a line of the form: <TT
1249 CLASS="LITERAL"
1250 >implements
1251 CYGINT_HAL_I386_MEM_REAL_REGION_TOP</TT
1252 >. This allows packages
1253 such as RedBoot to detect the presence of this function so that they
1254 may call it.</P
1255 ><TABLE
1256 BORDER="5"
1257 BGCOLOR="#E0E0F0"
1258 WIDTH="70%"
1259 ><TR
1260 ><TD
1261 ><PRE
1262 CLASS="PROGRAMLISTING"
1263 >&#13;    cdl_interface CYGINT_HAL_I386_MEM_REAL_REGION_TOP {
1264         display  "Implementations of hal_i386_mem_real_region_top()"
1265     }
1266     
1267 }</PRE
1268 ></TD
1269 ></TR
1270 ></TABLE
1271 ></DIV
1272 ></DIV
1273 ><DIV
1274 CLASS="NAVFOOTER"
1275 ><HR
1276 ALIGN="LEFT"
1277 WIDTH="100%"><TABLE
1278 SUMMARY="Footer navigation table"
1279 WIDTH="100%"
1280 BORDER="0"
1281 CELLPADDING="0"
1282 CELLSPACING="0"
1283 ><TR
1284 ><TD
1285 WIDTH="33%"
1286 ALIGN="left"
1287 VALIGN="top"
1288 ><A
1289 HREF="hal-porting-variant.html"
1290 ACCESSKEY="P"
1291 >Prev</A
1292 ></TD
1293 ><TD
1294 WIDTH="34%"
1295 ALIGN="center"
1296 VALIGN="top"
1297 ><A
1298 HREF="ecos-ref.html"
1299 ACCESSKEY="H"
1300 >Home</A
1301 ></TD
1302 ><TD
1303 WIDTH="33%"
1304 ALIGN="right"
1305 VALIGN="top"
1306 ><A
1307 HREF="hal-future-developments.html"
1308 ACCESSKEY="N"
1309 >Next</A
1310 ></TD
1311 ></TR
1312 ><TR
1313 ><TD
1314 WIDTH="33%"
1315 ALIGN="left"
1316 VALIGN="top"
1317 >Variant HAL Porting</TD
1318 ><TD
1319 WIDTH="34%"
1320 ALIGN="center"
1321 VALIGN="top"
1322 ><A
1323 HREF="hal-porting-guide.html"
1324 ACCESSKEY="U"
1325 >Up</A
1326 ></TD
1327 ><TD
1328 WIDTH="33%"
1329 ALIGN="right"
1330 VALIGN="top"
1331 >Future developments</TD
1332 ></TR
1333 ></TABLE
1334 ></DIV
1335 ></BODY
1336 ></HTML
1337 >