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. -->
12 >Writing New Devices - target</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
22 TITLE="eCos Synthetic Target"
23 HREF="hal-synth-arch.html"><LINK
26 HREF="synth-syscalls.html"><LINK
28 TITLE="Writing New Devices - host"
29 HREF="synth-new-host.html"></HEAD
40 SUMMARY="Header navigation table"
49 >eCos Reference Manual</TH
57 HREF="synth-syscalls.html"
71 HREF="synth-new-host.html"
82 NAME="SYNTH-NEW-TARGET">Writing New Devices - target</H1
90 >Writing New Devices -- extending the synthetic target, target-side</DIV
92 CLASS="REFSYNOPSISDIV"
108 CLASS="FUNCSYNOPSISINFO"
109 >#include <cyg/hal/hal_io.h>
118 >int synth_auxiliary_instantiate</CODE
119 >(const char* package, const char* version, const char* device, const char* instance, const char* data);</CODE
125 >void synth_auxiliary_xchgmsg</CODE
126 >(int device_id, int request, int arg1, int arg2, const unsigned char* txdata, int txlen, int* reply, unsigned char* rxdata, int* rxlen, int max_rxlen);</CODE
135 NAME="SYNTH-NEW-TARGET-DESCRIPTION"
140 >In some ways writing a device driver for the synthetic target is very
141 similar to writing one for a real target. Obviously it has to provide
142 the standard interface for that class of device, so for example an
143 ethernet device has to provide <TT
154 functions. Many devices will involve interrupts, so the driver
155 contains ISR and DSR functions and will call
158 >cyg_drv_interrupt_create</TT
162 >cyg_drv_interrupt_acknowledge</TT
167 >In other ways writing a device driver for the synthetic target is very
168 different. Usually the driver will not have any direct access to the
169 underlying hardware. In fact for some devices the I/O may not involve
170 real hardware, instead everything is emulated by widgets on the
171 graphical display. Therefore the driver cannot just peek and poke
172 device registers, instead it must interact with host-side code by
173 exchanging message. The synthetic target HAL provides a function
176 >synth_auxiliary_xchgmsg</TT
180 >Initialization of a synthetic target device driver is also very
181 different. On real targets the device hardware already exists when the
182 driver's initialization routine runs. On the synthetic target it is
183 first necessary to instantiate the device inside the I/O auxiliary, by
186 >synth_auxiliary_instantiate</TT
188 function performs a special message exchange with the I/O auxiliary,
189 causing it to load a Tcl script for the desired type of device and run
190 an instantiation procedure within that script.
193 >Use of the I/O auxiliary is optional: if the user does not specify
197 > on the command line then the auxiliary will not
198 be started and hence most I/O operations will not be possible. Device
199 drivers should allow for this possibility, for example by just
200 discarding any data that gets written. The HAL exports a flag
203 >synth_auxiliary_running</TT
204 > which should be checked.
210 NAME="SYNTH-NEW-TARGET-INSTANTIATE"
213 >Instantiating a Device</H2
215 >Device instantiation should happen during the C++ prioritized static
216 constructor phase of system initialization, before control switches to
220 > and general application code. This
221 ensures that there is a clearly defined point at which the I/O
222 auxiliary knows that all required devices have been loaded. It can
223 then perform various consistency checks and clean-ups, run the user's
227 > script, and make the main window
231 >For standard devices generic eCos I/O code will call the device
232 initialization routines at the right time, iterating through the
236 > table in a static constructor. The same
237 holds for network devices and file systems. For more custom devices
238 code like the following can be used:
247 CLASS="PROGRAMLISTING"
248 >#include <cyg/infra/cyg_type.h>
255 static mydev_init mydev_init_object CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO);</PRE
260 >Some care has to be taken because the object
263 >mydev_init_object</TT
264 > will typically not be referenced
265 by other code, and hence may get eliminated at link-time. If the code
266 is part of an eCos package then problems can be avoided by putting the
279 CLASS="PROGRAMLISTING"
280 >cdl_package CYGPKG_DEVS_MINE {
282 compile -library=libextras.a init.cxx
288 >For devices inside application code the same can be achieved by
289 linking the relevant module as a <TT
293 than putting it in a <TT
299 >In the device initialization routine the main operation is a call to
302 >synth_auxiliary_instantiate</TT
304 arguments, all of which should be strings:
318 >For device drivers which are eCos packages this should be a directory
319 path relative to the eCos repository, for example
322 >devs/eth/synth/ecosynth</TT
323 >. This will allow the I/O
324 auxiliary to find the various host-side support files for this package
325 within the install tree. If the device is application-specific and not
326 part of an eCos package then a NULL pointer can be used, causing the
327 I/O auxiliary to search for the support files in the current directory
342 >For eCos packages this argument should be the version of the package
343 that is being used, for example <TT
347 way to get this version is to use the
350 >SYNTH_MAKESTRING</TT
351 > macro on the package name.
352 If the device is application-specific then a NULL pointer should be
363 >This argument specifies the type of device being instantiated, for
367 >. More specifically the I/O
368 auxiliary will append a <TT
372 the name of a Tcl script that will handle all I/O requests for the
373 device. If the application requires several instances of a type
374 of device then the script will only be loaded once, but the script
375 will contain an instantiation procedure that will be called for each
386 >If it is possible to have multiple instances of a device then this
387 argument identifies the particular instance, for example
405 >This argument can be used to pass additional initialization data from
406 eCos to the host-side support. This is useful for devices where eCos
407 configury must control certain aspects of the device, rather than
408 host-side configury such as the target definition file, because eCos
409 has compile-time dependencies on some or all of the relevant options.
410 An example might be an emulated frame buffer where eCos has been
411 statically configured for a particular screen size, orientation and
412 depth. There is no fixed format for this string, it will be
413 interpreted only by the device-specific host-side Tcl script. However
414 the string length should be limited to a couple of hundred bytes to
415 avoid possible buffer overflow problems.
421 >Typical usage would look like:
430 CLASS="PROGRAMLISTING"
431 > if (!synth_auxiliary_running) {
434 id = synth_auxiliary_instantiate("devs/eth/synth/ecosynth",
435 SYNTH_MAKESTRING(CYGPKG_DEVS_ETH_ECOSYNTH),
438 (const char*) 0);</PRE
443 >The return value will be a device identifier which can be used for
444 subsequent calls to <TT
446 >synth_auxiliary_xchgmsg</TT
448 the device could not be instantiated then <TT
452 be returned. It is the responsibility of the host-side software to
453 issue suitable diagnostics explaining what went wrong, so normally the
454 target-side code should fail silently.
457 >Once the desired device has been instantiated, often it will be
458 necessary to do some additional initialization by a message exchange.
459 For example an ethernet device might need information from the
460 host-side about the MAC address, the <A
461 HREF="synth-new-target.html#SYNTH-NEW-TARGET-INTERRUPTS"
464 whether or not multicasting is supported.
470 NAME="SYNTH-NEW-TARGET-XCHGMSG"
473 >Communicating with a Device</H2
475 >Once a device has been instantiated it is possible to perform I/O by
476 sending messages to the appropriate Tcl script running inside the
477 auxiliary, and optionally getting back replies. I/O operations are
478 always initiated by the eCos target-side, it is not possible for the
479 host-side software to initiate data transfers. However the host-side
480 can raise interrupts, and the interrupt handler inside the target can
481 then exchange one or more messages with the host.
484 >There is a single function to perform I/O operations,
487 >synth_auxiliary_xchgmsg</TT
488 >. This takes the following
503 >This should be one of the identifiers returned by a previous
506 >synth_auxiliary_instantiate</TT
508 particular device which should perform some I/O.
518 >Request are just signed 32-bit integers that identify the particular
519 I/O operation being requested. There is no fixed set of codes, instead
520 each type of device can define its own.
533 >For some requests it is convenient to pass one or two additional
534 parameters alongside the request code. For example an ethernet device
535 could define a multicast-all request, with <TT
539 controlling whether this mode should be enabled or disabled. Both
547 32-bit integers, and their values are interpreted only by the
548 device-specific Tcl script.
561 >Some I/O operations may involve sending additional data, for example
562 an ethernet packet. Alternatively a control operation may require many
563 more parameters than can easily be encoded in <TT
570 >, so those parameters have to be placed in
571 a suitable buffer and extracted at the other end.
575 > is an arbitrary buffer of
579 > bytes that should be sent to the host-side.
580 There is no specific upper bound on the number of bytes that can be
581 sent, but usually it is a good idea to allocate the transmit buffer
582 statically and keep transfers down to at most several kilobytes.
592 >If the host-side is expected to send a reply message then
596 > should be a pointer to an integer variable
597 and will be updated with a reply code, a simple 32-bit integer. The
598 synthetic target HAL code assumes that the host-side and target-side
599 agree on the protocol being used: if the host-side will not send a
600 reply to this message then the <TT
604 should be a NULL pointer; otherwise the host-side must always send
605 a reply code and the <TT
608 > argument must be valid.
621 >Some operations may involve additional data coming from the host-side,
622 for example an incoming ethernet packet. <TT
626 should be a suitably-sized buffer, and <TT
630 pointer to an integer variable that will end up containing the number
631 of bytes that were actually received. These arguments will only be
632 used if the host-side is expected to send a reply and hence the
636 > argument was not NULL.
646 >If a reply to this message is expected and that reply may involve
650 > limits the size of that
651 reply. In other words, it corresponds to the size of the
661 >Most I/O operations involve only some of the arguments. For example
662 transmitting an ethernet packet would use the
673 > fields (in addition to
677 > which is always required), but would not
685 reply would be expected. Receiving an ethernet packet would involve
703 > is needed to get any reply from the host-side
704 at all, and could be used to indicate whether or not any more packets
705 are buffered up. A control operation such as enabling multicast mode
713 but none of the remaining arguments.
719 NAME="SYNTH-NEW-TARGET-INTERRUPTS"
722 >Interrupt Handling</H2
724 >Interrupt handling in the synthetic target is much the same as on a
725 real target. An interrupt object is created using
728 >cyg_drv_interrupt_create</TT
729 >, attached, and unmasked.
730 The emulated device - in other words the Tcl script running inside the
731 I/O auxiliary - can raise an interrupt. Subject to interrupts being
732 disabled and the appropriate vector being masked, the system will
733 invoke the specified ISR function. The synthetic target HAL
734 implementation does have some limitations: there is no support for
735 nested interrupts, interrupt priorities, or a separate interrupt
736 stack. Supporting those might be appropriate when targetting a
737 simulator that attempts to model real hardware accurately, but not for
738 the simple emulation provided by the synthetic target.
741 >Of course the actual implementation of the ISR and DSR functions will
742 be rather different for a synthetic target device driver. For real
743 hardware the device driver will interact with the device by reading
744 and writing device registers, managing DMA engines, and the like. A
745 synthetic target driver will instead call
748 >synth_auxiliary_xchgmsg</TT
753 >There is one other significant difference between interrupt handling
754 on the synthetic target and on real hardware. Usually the eCos code
755 will know which interrupt vectors are used for which devices. That
756 information is fixed when the target hardware is designed. With the
757 synthetic target interrupt vectors are assigned to devices on the host
758 side, either via the target definition file or dynamically when the
759 device is instantiated. Therefore the initialization code for a
760 target-side device driver will need to request interrupt vector
761 information from the host-side, via a message exchange. Such interrupt
762 vectors will be in the range 1 to 31 inclusive, with interrupt 0 being
763 reserved for the real-time clock.
771 SUMMARY="Footer navigation table"
782 HREF="synth-syscalls.html"
800 HREF="synth-new-host.html"
816 HREF="hal-synth-arch.html"
824 >Writing New Devices - host</TD