]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - doc/html/ref/compat-uitron-configuration-faq.html
Initial revision
[karo-tx-redboot.git] / doc / html / ref / compat-uitron-configuration-faq.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 >µITRON Configuration FAQ</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="µITRON API"
23 HREF="compat-uitron-microitron-api.html"><LINK
24 REL="PREVIOUS"
25 TITLE="   Network Support Functions"
26 HREF="compat-uitron-network-support-functions.html"><LINK
27 REL="NEXT"
28 TITLE="TCP/IP Stack Support for eCos"
29 HREF="net-common-tcpip.html"></HEAD
30 ><BODY
31 CLASS="SECT1"
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="compat-uitron-network-support-functions.html"
58 ACCESSKEY="P"
59 >Prev</A
60 ></TD
61 ><TD
62 WIDTH="80%"
63 ALIGN="center"
64 VALIGN="bottom"
65 >Chapter 32. &micro;ITRON API</TD
66 ><TD
67 WIDTH="10%"
68 ALIGN="right"
69 VALIGN="bottom"
70 ><A
71 HREF="net-common-tcpip.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="SECT1"
82 ><H1
83 CLASS="SECT1"
84 ><A
85 NAME="COMPAT-UITRON-CONFIGURATION-FAQ">&micro;ITRON Configuration FAQ</H1
86 ><P
87 ><SPAN
88 CLASS="emphasis"
89 ><I
90 CLASS="EMPHASIS"
91 >Q: How are &micro;ITRON objects created?</I
92 ></SPAN
93 ></P
94 ><P
95 >For each type of uITRON object (tasks, semaphores, flags, mboxes, mpf, mpl)
96 these two quantities are controlled by configuration:</P
97 ><P
98 ></P
99 ><UL
100 ><LI
101 ><P
102 >The <SPAN
103 CLASS="emphasis"
104 ><I
105 CLASS="EMPHASIS"
106 >maximum</I
107 ></SPAN
108 > number of this type of object.</P
109 ></LI
110 ><LI
111 ><P
112 >The number of these objects which exist <SPAN
113 CLASS="emphasis"
114 ><I
115 CLASS="EMPHASIS"
116 >initially</I
117 ></SPAN
118 >.</P
119 ></LI
120 ></UL
121 ><P
122 >This is assuming that for the relevant object type,
123 <SPAN
124 CLASS="emphasis"
125 ><I
126 CLASS="EMPHASIS"
127 >create</I
128 ></SPAN
129 > and <SPAN
130 CLASS="emphasis"
131 ><I
132 CLASS="EMPHASIS"
133 >delete</I
134 ></SPAN
135 >
136 operations are enabled; enabled is the default.  For example, the option
137 <TT
138 CLASS="LITERAL"
139 >CYGPKG_UITRON_MBOXES_CREATE_DELETE</TT
140 >
141 controls whether the functions
142 <TT
143 CLASS="FUNCTION"
144 >cre_mbx()</TT
145 >
146 and
147 <TT
148 CLASS="FUNCTION"
149 >del_mbx()</TT
150 >
151 exist in the API.  If not, then the maximum number of
152 mboxes is the same as the initial number of mboxes, and so on for all
153 &micro;ITRON object types.</P
154 ><P
155 >Mboxes have no initialization, so there are only a few, simple
156 configuration options:</P
157 ><P
158 ></P
159 ><UL
160 ><LI
161 ><P
162 ><TT
163 CLASS="LITERAL"
164 >CYGNUM_UITRON_MBOXES</TT
165 >
166 is the total number of mboxes that you can have in the
167 system.  By default this is 4, so you can use mboxes 1,2,3 and 4.  You
168 cannot create mboxes outside this range; trying to
169 <TT
170 CLASS="FUNCTION"
171 >cre_mbx(5,...)</TT
172 >
173 will return an error.</P
174 ></LI
175 ><LI
176 ><P
177 ><TT
178 CLASS="LITERAL"
179 >CYGNUM_UITRON_MBOXES_INITIALLY</TT
180 >
181 is the number of mboxes created
182 automatically for you, during startup.  By default this is 4, so all 4
183 mboxes exist already, and an attempt to create one of these
184 eg. <TT
185 CLASS="FUNCTION"
186 >cre_mbx(3,...)</TT
187 >
188 will return an error because the mbox in quesion already
189 exists.  You can delete a pre-existing mbox, and then re-create it.</P
190 ></LI
191 ></UL
192 ><P
193 >If you change 
194 <TT
195 CLASS="LITERAL"
196 >CYGNUM_UITRON_MBOXES_INITIALLY</TT
197 >,
198 for example to 0, no mboxes
199 are created automatically for you during startup.  Any attempt to use an
200 mbox without creating it will return E_NOEXS because the mbox does not
201 exist.  You can create an mbox, say <TT
202 CLASS="FUNCTION"
203 >cre_mbx(3,...)</TT
204 >
205 and then use it, say
206 <TT
207 CLASS="FUNCTION"
208 >snd_msg(3,&amp;foo)</TT
209 >, and all will be well.</P
210 ><P
211 ><SPAN
212 CLASS="emphasis"
213 ><I
214 CLASS="EMPHASIS"
215 >Q: How are &micro;ITRON objects initialized?</I
216 ></SPAN
217 ></P
218 ><P
219 >Some object types have optional initialization.  Semaphores are an
220 example.  You could have 
221 <TT
222 CLASS="LITERAL"
223 >CYGNUM_UITRON_SEMAS</TT
224 >=10 and
225 <TT
226 CLASS="LITERAL"
227 >CYGNUM_UITRON_SEMAS_INITIALLY</TT
228 >=5
229 which means you can use semaphores 1-5
230 straight off, but you must create semaphores 6-10 before you can use them.
231 If you decide not to initialize semaphores, semaphores 1-5 will have an
232 initial count of zero.  If you decide to initialize them, you must supply
233 a dummy initializer for semaphores 6-10 also.  For example,
234 in terms of the configuration output in
235 <TT
236 CLASS="FILENAME"
237 >pkgconf/uitron.h</TT
238 >:</P
239 ><TABLE
240 BORDER="5"
241 BGCOLOR="#E0E0F0"
242 WIDTH="70%"
243 ><TR
244 ><TD
245 ><PRE
246 CLASS="PROGRAMLISTING"
247 >   #define CYGDAT_UITRON_SEMA_INITIALIZERS \
248         CYG_UIT_SEMA(  1 ),     \
249         CYG_UIT_SEMA(  0 ),     \
250         CYG_UIT_SEMA(  0 ),     \
251         CYG_UIT_SEMA( 99 ),     \
252         CYG_UIT_SEMA(  1 ),     \
253         CYG_UIT_SEMA_NOEXS,     \
254         CYG_UIT_SEMA_NOEXS,     \
255         CYG_UIT_SEMA_NOEXS,     \
256         CYG_UIT_SEMA_NOEXS,     \
257         CYG_UIT_SEMA_NOEXS</PRE
258 ></TD
259 ></TR
260 ></TABLE
261 ><P
262 >Semaphore 1 will have initial count 1, semaphores 2 and 3 will be zero,
263 number 4 will be 99 initially, 5 will be one and numbers 6 though 10 do not
264 exist initially.</P
265 ><P
266 >Aside: this is how the definition of the symbol would appear in the
267 configuration header file <TT
268 CLASS="FILENAME"
269 >pkgconf/uitron.h</TT
270 > &#8212;
271 unfortunately editing such a long, multi-line definition is somewhat
272 cumbersome in the GUI config tool in current releases.  The macros
273 <TT
274 CLASS="LITERAL"
275 >CYG_UIT_SEMA()</TT
276 >
277 &#8212; to create a semaphore initializer &#8212; and
278 <TT
279 CLASS="LITERAL"
280 >CYG_UIT_SEMA_NOEXS</TT
281 >
282 &#8212; to invoke a dummy initializer &#8212;
283 are provided in in the environment to help with this.  Similar macros are
284 provided for other object types.  The resulting #define symbol is used in
285 the context of a C++ array initializer, such as:
286 <TABLE
287 BORDER="5"
288 BGCOLOR="#E0E0F0"
289 WIDTH="70%"
290 ><TR
291 ><TD
292 ><PRE
293 CLASS="PROGRAMLISTING"
294 >Cyg_Counting_Semaphore2 cyg_uitron_SEMAS[ CYGNUM_UITRON_SEMAS ] = {
295         CYGDAT_UITRON_SEMA_INITIALIZERS
296 };</PRE
297 ></TD
298 ></TR
299 ></TABLE
300 >
301 which is eventually macro-processed to give
302 <TABLE
303 BORDER="5"
304 BGCOLOR="#E0E0F0"
305 WIDTH="70%"
306 ><TR
307 ><TD
308 ><PRE
309 CLASS="PROGRAMLISTING"
310 >Cyg_Counting_Semaphore2 cyg_uitron_SEMAS[ 10 ] = {
311         Cyg_Counting_Semaphore2( ( 1 ) ), 
312         Cyg_Counting_Semaphore2( ( 0 ) ), 
313         Cyg_Counting_Semaphore2( ( 0 ) ), 
314         Cyg_Counting_Semaphore2( ( 99 ) ), 
315         Cyg_Counting_Semaphore2( ( 1 ) ), 
316         Cyg_Counting_Semaphore2(0), 
317         Cyg_Counting_Semaphore2(0), 
318         Cyg_Counting_Semaphore2(0), 
319         Cyg_Counting_Semaphore2(0), 
320         Cyg_Counting_Semaphore2(0), 
321 };</PRE
322 ></TD
323 ></TR
324 ></TABLE
325 >
326 so you can see how it is necessary to include the dummy entries in that
327 definition, otherwise the resulting code will not compile correctly.</P
328 ><P
329 >If you choose 
330 <TT
331 CLASS="LITERAL"
332 >CYGNUM_UITRON_SEMAS_INITIALLY</TT
333 >=0
334 it is meaningless to initialize them, for they must be created and so
335 initialized then, before use.</P
336 ><P
337 ><SPAN
338 CLASS="emphasis"
339 ><I
340 CLASS="EMPHASIS"
341 >Q: What about &micro;ITRON tasks?</I
342 ></SPAN
343 ></P
344 ><P
345 >Some object types require initialization.  Tasks are an example of this.
346 You must provide a task with a priority, a function to enter when the task
347 starts, a name (for debugging purposes), and some memory to use for the stack.
348 For example (again in terms of the resulting
349 definitions in <TT
350 CLASS="FILENAME"
351 >pkgconf/uitron.h</TT
352 >):</P
353 ><TABLE
354 BORDER="5"
355 BGCOLOR="#E0E0F0"
356 WIDTH="70%"
357 ><TR
358 ><TD
359 ><PRE
360 CLASS="PROGRAMLISTING"
361 >#define CYGNUM_UITRON_TASKS 4           // valid task ids are 1,2,3,4
362 #define CYGNUM_UITRON_TASKS_INITIALLY 4 // they all exist at start
363
364 #define CYGDAT_UITRON_TASK_EXTERNS              \
365 extern "C" void startup( unsigned int );        \
366 extern "C" void worktask( unsigned int );       \
367 extern "C" void lowtask( unsigned int );        \
368 static char stack1[ CYGNUM_UITRON_STACK_SIZE ], \
369             stack2[ CYGNUM_UITRON_STACK_SIZE ], \
370             stack3[ CYGNUM_UITRON_STACK_SIZE ], \
371             stack4[ CYGNUM_UITRON_STACK_SIZE ];
372
373 #define CYGDAT_UITRON_TASK_INITIALIZERS \
374  CYG_UIT_TASK("main task", 8, startup,  &amp;stack1, sizeof( stack1 )), \
375  CYG_UIT_TASK("worker 2" , 9, worktask, &amp;stack2, sizeof( stack2 )), \
376  CYG_UIT_TASK("worker 3" , 9, worktask, &amp;stack3, sizeof( stack3 )), \
377  CYG_UIT_TASK("low task" ,20, lowtask,  &amp;stack4, sizeof( stack4 )), \&#13;</PRE
378 ></TD
379 ></TR
380 ></TABLE
381 ><P
382 >So this example has all four tasks statically configured to exist, ready to
383 run, from the start of time.  The &#8220;main task&#8221; runs a routine
384 called <TT
385 CLASS="FUNCTION"
386 >startup()</TT
387 > at priority 8.  Two
388 &#8220;worker&#8221; tasks run both a priority 9, and a &#8220;low
389 priority&#8221; task runs at priority 20 to do useful non-urgent background
390 work.</P
391 ><TABLE
392 BORDER="5"
393 BGCOLOR="#E0E0F0"
394 WIDTH="70%"
395 ><TR
396 ><TD
397 ><PRE
398 CLASS="SCREEN"
399 >Task ID | Exists at | Function | Priority | Stack   | Stack
400  number |  startup  |  entry   |          | address | size
401 --------+-----------+----------+----------+---------+----------
402    1    |    Yes    |  startup |    8     | &amp;stack1 | CYGNUM...
403    2    |    Yes    | worktask |    9     | &amp;stack2 | CYGNUM...
404    3    |    Yes    | worktask |    9     | &amp;stack3 | CYGNUM...
405    4    |    Yes    |  lowtask |   20     | &amp;stack4 | CYGNUM...
406 --------+-----------+----------+----------+---------+----------</PRE
407 ></TD
408 ></TR
409 ></TABLE
410 ><P
411 ><SPAN
412 CLASS="emphasis"
413 ><I
414 CLASS="EMPHASIS"
415 >Q: How can I create &micro;ITRON tasks in the program?</I
416 ></SPAN
417 ></P
418 ><P
419 >You must provide free slots in the task table in which to create new tasks,
420 by configuring the number of tasks existing initially to be smaller than
421 the total.
422 For a task ID which does not initially exist, it will be told what routine
423 to call, and what priority it is, when the task is created.  But you must
424 still set aside memory for the task to use for its stack, and give it a
425 name during initialization.  For example:</P
426 ><TABLE
427 BORDER="5"
428 BGCOLOR="#E0E0F0"
429 WIDTH="70%"
430 ><TR
431 ><TD
432 ><PRE
433 CLASS="PROGRAMLISTING"
434 >#define CYGNUM_UITRON_TASKS 4           // valid task ids are 1-4
435 #define CYGNUM_UITRON_TASKS_INITIALLY 1 // only task #1 exists
436
437 #define CYGDAT_UITRON_TASK_EXTERNS \
438 extern "C" void startup( unsigned int ); \
439 static char stack1[ CYGNUM_UITRON_STACK_SIZE ], \
440             stack2[ CYGNUM_UITRON_STACK_SIZE ], \
441             stack3[ CYGNUM_UITRON_STACK_SIZE ], \
442             stack4[ CYGNUM_UITRON_STACK_SIZE ];
443
444 #define CYGDAT_UITRON_TASK_INITIALIZERS \
445    CYG_UIT_TASK( "main", 8, startup, &amp;stack1, sizeof( stack1 ) ), \
446    CYG_UIT_TASK_NOEXS( "slave",      &amp;stack2, sizeof( stack2 ) ), \
447    CYG_UIT_TASK_NOEXS( "slave2",     &amp;stack3, sizeof( stack3 ) ), \
448    CYG_UIT_TASK_NOEXS( "slave3",     &amp;stack4, sizeof( stack4 ) ), \&#13;</PRE
449 ></TD
450 ></TR
451 ></TABLE
452 ><P
453 >So tasks numbered 2,3 and 4 have been given their stacks during startup,
454 though they do not yet exist in terms of <TT
455 CLASS="FUNCTION"
456 >cre_tsk()</TT
457 > and
458 <TT
459 CLASS="FUNCTION"
460 >del_tsk()</TT
461 > so you can create tasks 2&#8211;4 at
462 runtime.</P
463 ><TABLE
464 BORDER="5"
465 BGCOLOR="#E0E0F0"
466 WIDTH="70%"
467 ><TR
468 ><TD
469 ><PRE
470 CLASS="SCREEN"
471 >Task ID | Exists at | Function | Priority | Stack   | Stack
472  number |  startup  |  entry   |          | address | size
473 --------+-----------+----------+----------+---------+----------
474    1    |    Yes    |  startup |    8     | &amp;stack1 | CYGNUM...
475    2    |    No     |   N/A    |   N/A    | &amp;stack2 | CYGNUM...
476    3    |    No     |   N/A    |   N/A    | &amp;stack3 | CYGNUM...
477    4    |    No     |   N/A    |   N/A    | &amp;stack4 | CYGNUM...
478 --------+-----------+----------+----------+---------+----------</PRE
479 ></TD
480 ></TR
481 ></TABLE
482 ><P
483 >(you must have at least one task at startup in order that the system can
484  actually run; this is not so for other uITRON object types)</P
485 ><P
486 ><SPAN
487 CLASS="emphasis"
488 ><I
489 CLASS="EMPHASIS"
490 >Q: Can I have different stack sizes for &micro;ITRON tasks?</I
491 ></SPAN
492 ></P
493 ><P
494 >Simply set aside different amounts of memory for each task to use for its
495 stack.  Going back to a typical default setting for the &micro;ITRON tasks,
496 the definitions in <TT
497 CLASS="FILENAME"
498 >pkgconf/uitron.h</TT
499 > might look like this:</P
500 ><TABLE
501 BORDER="5"
502 BGCOLOR="#E0E0F0"
503 WIDTH="70%"
504 ><TR
505 ><TD
506 ><PRE
507 CLASS="PROGRAMLISTING"
508 >#define CYGDAT_UITRON_TASK_EXTERNS \
509 extern "C" void task1( unsigned int ); \
510 extern "C" void task2( unsigned int ); \
511 extern "C" void task3( unsigned int ); \
512 extern "C" void task4( unsigned int ); \
513 static char stack1[ CYGNUM_UITRON_STACK_SIZE ], \
514             stack2[ CYGNUM_UITRON_STACK_SIZE ], \
515             stack3[ CYGNUM_UITRON_STACK_SIZE ], \
516             stack4[ CYGNUM_UITRON_STACK_SIZE ];
517   
518 #define CYGDAT_UITRON_TASK_INITIALIZERS \
519   CYG_UIT_TASK( "t1", 1, task1, &amp;stack1, CYGNUM_UITRON_STACK_SIZE ), \
520   CYG_UIT_TASK( "t2", 2, task2, &amp;stack2, CYGNUM_UITRON_STACK_SIZE ), \
521   CYG_UIT_TASK( "t3", 3, task3, &amp;stack3, CYGNUM_UITRON_STACK_SIZE ), \
522   CYG_UIT_TASK( "t4", 4, task4, &amp;stack4, CYGNUM_UITRON_STACK_SIZE )&#13;</PRE
523 ></TD
524 ></TR
525 ></TABLE
526 ><P
527 >Note that 
528 <TT
529 CLASS="LITERAL"
530 >CYGNUM_UITRON_STACK_SIZE</TT
531 >
532 is used to control the size of the stack
533 objects themselves, and to tell the system what size stack is being provided.</P
534 ><P
535 >Suppose instead stack sizes of 2000, 1000, 800 and 800 were required:
536 this could be achieved by using the GUI config tool to edit these
537 options, or editting the <TT
538 CLASS="FILENAME"
539 >.ecc</TT
540 > file to get these
541 results in <TT
542 CLASS="FILENAME"
543 >pkgconf/uitron.h</TT
544 >:</P
545 ><TABLE
546 BORDER="5"
547 BGCOLOR="#E0E0F0"
548 WIDTH="70%"
549 ><TR
550 ><TD
551 ><PRE
552 CLASS="PROGRAMLISTING"
553 >#define CYGDAT_UITRON_TASK_EXTERNS \
554 extern "C" void task1( unsigned int ); \
555 extern "C" void task2( unsigned int ); \
556 extern "C" void task3( unsigned int ); \
557 extern "C" void task4( unsigned int ); \
558 static char stack1[ 2000 ], \
559             stack2[ 1000 ], \
560             stack3[  800 ], \
561             stack4[  800 ];
562  
563 #define CYGDAT_UITRON_TASK_INITIALIZERS \
564       CYG_UIT_TASK( "t1", 1, task1, &amp;stack1, sizeof( stack1 ) ), \
565       CYG_UIT_TASK( "t2", 2, task2, &amp;stack2, sizeof( stack2 ) ), \
566       CYG_UIT_TASK( "t3", 3, task3, &amp;stack3, sizeof( stack3 ) ), \
567       CYG_UIT_TASK( "t4", 4, task4, &amp;stack4, sizeof( stack4 ) )</PRE
568 ></TD
569 ></TR
570 ></TABLE
571 ><P
572 >Note that the sizeof() operator has been used to tell the system what size
573 stacks are provided, rather than quoting a number (which is difficult for
574 maintenance) or the symbol 
575 <TT
576 CLASS="LITERAL"
577 >CYGNUM_UITRON_STACK_SIZE</TT
578 >
579 (which is wrong).</P
580 ><P
581 >We recommend using (if available in your release) the stacksize symbols
582 provided in the architectural HAL for your target, called
583 <TT
584 CLASS="LITERAL"
585 >CYGNUM_HAL_STACK_SIZE_TYPICAL</TT
586 >
587 and 
588 <TT
589 CLASS="LITERAL"
590 >CYGNUM_HAL_STACK_SIZE_MINIMUM</TT
591 >.
592 So a better (more portable) version of the above might be:</P
593 ><TABLE
594 BORDER="5"
595 BGCOLOR="#E0E0F0"
596 WIDTH="70%"
597 ><TR
598 ><TD
599 ><PRE
600 CLASS="PROGRAMLISTING"
601 >#define CYGDAT_UITRON_TASK_EXTERNS \
602 extern "C" void task1( unsigned int ); \
603 extern "C" void task2( unsigned int ); \
604 extern "C" void task3( unsigned int ); \
605 extern "C" void task4( unsigned int ); \
606 static char stack1[ CYGNUM_HAL_STACK_SIZE_TYPICAL + 1200 ], \
607             stack2[ CYGNUM_HAL_STACK_SIZE_TYPICAL +  200 ], \
608             stack3[ CYGNUM_HAL_STACK_SIZE_TYPICAL        ], \
609             stack4[ CYGNUM_HAL_STACK_SIZE_TYPICAL        ];
610
611 #define CYGDAT_UITRON_TASK_INITIALIZERS \
612       CYG_UIT_TASK( "t1", 1, task1, &amp;stack1, sizeof( stack1 ) ), \
613       CYG_UIT_TASK( "t2", 2, task2, &amp;stack2, sizeof( stack2 ) ), \
614       CYG_UIT_TASK( "t3", 3, task3, &amp;stack3, sizeof( stack3 ) ), \
615       CYG_UIT_TASK( "t4", 4, task4, &amp;stack4, sizeof( stack4 ) )</PRE
616 ></TD
617 ></TR
618 ></TABLE
619 ></DIV
620 ><DIV
621 CLASS="NAVFOOTER"
622 ><HR
623 ALIGN="LEFT"
624 WIDTH="100%"><TABLE
625 SUMMARY="Footer navigation table"
626 WIDTH="100%"
627 BORDER="0"
628 CELLPADDING="0"
629 CELLSPACING="0"
630 ><TR
631 ><TD
632 WIDTH="33%"
633 ALIGN="left"
634 VALIGN="top"
635 ><A
636 HREF="compat-uitron-network-support-functions.html"
637 ACCESSKEY="P"
638 >Prev</A
639 ></TD
640 ><TD
641 WIDTH="34%"
642 ALIGN="center"
643 VALIGN="top"
644 ><A
645 HREF="ecos-ref.html"
646 ACCESSKEY="H"
647 >Home</A
648 ></TD
649 ><TD
650 WIDTH="33%"
651 ALIGN="right"
652 VALIGN="top"
653 ><A
654 HREF="net-common-tcpip.html"
655 ACCESSKEY="N"
656 >Next</A
657 ></TD
658 ></TR
659 ><TR
660 ><TD
661 WIDTH="33%"
662 ALIGN="left"
663 VALIGN="top"
664 >Network Support Functions</TD
665 ><TD
666 WIDTH="34%"
667 ALIGN="center"
668 VALIGN="top"
669 ><A
670 HREF="compat-uitron-microitron-api.html"
671 ACCESSKEY="U"
672 >Up</A
673 ></TD
674 ><TD
675 WIDTH="33%"
676 ALIGN="right"
677 VALIGN="top"
678 >TCP/IP Stack Support for eCos</TD
679 ></TR
680 ></TABLE
681 ></DIV
682 ></BODY
683 ></HTML
684 >