<!-- Copyright (C) 2002 Red Hat, Inc. -->
|
<!-- Copyright (C) 2002 Red Hat, Inc. -->
|
<!-- This material may be distributed only subject to the terms -->
|
<!-- This material may be distributed only subject to the terms -->
|
<!-- and conditions set forth in the Open Publication License, v1.0 -->
|
<!-- and conditions set forth in the Open Publication License, v1.0 -->
|
<!-- or later (the latest version is presently available at -->
|
<!-- or later (the latest version is presently available at -->
|
<!-- http://www.opencontent.org/openpub/). -->
|
<!-- http://www.opencontent.org/openpub/). -->
|
<!-- Distribution of the work or derivative of the work in any -->
|
<!-- Distribution of the work or derivative of the work in any -->
|
<!-- standard (paper) book form is prohibited unless prior -->
|
<!-- standard (paper) book form is prohibited unless prior -->
|
<!-- permission is obtained from the copyright holder. -->
|
<!-- permission is obtained from the copyright holder. -->
|
<HTML
|
<HTML
|
><HEAD
|
><HEAD
|
><TITLE
|
><TITLE
|
>Writing New Devices - target</TITLE
|
>Writing New Devices - target</TITLE
|
><meta name="MSSmartTagsPreventParsing" content="TRUE">
|
><meta name="MSSmartTagsPreventParsing" content="TRUE">
|
<META
|
<META
|
NAME="GENERATOR"
|
NAME="GENERATOR"
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
|
"><LINK
|
"><LINK
|
REL="HOME"
|
REL="HOME"
|
TITLE="eCos Synthetic Target"
|
TITLE="eCos Synthetic Target"
|
HREF="hal-synth-arch.html"><LINK
|
HREF="hal-synth-arch.html"><LINK
|
REL="PREVIOUS"
|
REL="PREVIOUS"
|
TITLE="System Calls"
|
TITLE="System Calls"
|
HREF="synth-syscalls.html"><LINK
|
HREF="synth-syscalls.html"><LINK
|
REL="NEXT"
|
REL="NEXT"
|
TITLE="Writing New Devices - host"
|
TITLE="Writing New Devices - host"
|
HREF="synth-new-host.html"></HEAD
|
HREF="synth-new-host.html"></HEAD
|
><BODY
|
><BODY
|
CLASS="REFENTRY"
|
CLASS="REFENTRY"
|
BGCOLOR="#FFFFFF"
|
BGCOLOR="#FFFFFF"
|
TEXT="#000000"
|
TEXT="#000000"
|
LINK="#0000FF"
|
LINK="#0000FF"
|
VLINK="#840084"
|
VLINK="#840084"
|
ALINK="#0000FF"
|
ALINK="#0000FF"
|
><DIV
|
><DIV
|
CLASS="NAVHEADER"
|
CLASS="NAVHEADER"
|
><TABLE
|
><TABLE
|
SUMMARY="Header navigation table"
|
SUMMARY="Header navigation table"
|
WIDTH="100%"
|
WIDTH="100%"
|
BORDER="0"
|
BORDER="0"
|
CELLPADDING="0"
|
CELLPADDING="0"
|
CELLSPACING="0"
|
CELLSPACING="0"
|
><TR
|
><TR
|
><TH
|
><TH
|
COLSPAN="3"
|
COLSPAN="3"
|
ALIGN="center"
|
ALIGN="center"
|
>eCos Synthetic Target</TH
|
>eCos Synthetic Target</TH
|
></TR
|
></TR
|
><TR
|
><TR
|
><TD
|
><TD
|
WIDTH="10%"
|
WIDTH="10%"
|
ALIGN="left"
|
ALIGN="left"
|
VALIGN="bottom"
|
VALIGN="bottom"
|
><A
|
><A
|
HREF="synth-syscalls.html"
|
HREF="synth-syscalls.html"
|
ACCESSKEY="P"
|
ACCESSKEY="P"
|
>Prev</A
|
>Prev</A
|
></TD
|
></TD
|
><TD
|
><TD
|
WIDTH="80%"
|
WIDTH="80%"
|
ALIGN="center"
|
ALIGN="center"
|
VALIGN="bottom"
|
VALIGN="bottom"
|
></TD
|
></TD
|
><TD
|
><TD
|
WIDTH="10%"
|
WIDTH="10%"
|
ALIGN="right"
|
ALIGN="right"
|
VALIGN="bottom"
|
VALIGN="bottom"
|
><A
|
><A
|
HREF="synth-new-host.html"
|
HREF="synth-new-host.html"
|
ACCESSKEY="N"
|
ACCESSKEY="N"
|
>Next</A
|
>Next</A
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
><HR
|
><HR
|
ALIGN="LEFT"
|
ALIGN="LEFT"
|
WIDTH="100%"></DIV
|
WIDTH="100%"></DIV
|
><H1
|
><H1
|
><A
|
><A
|
NAME="SYNTH-NEW-TARGET">Writing New Devices - target</H1
|
NAME="SYNTH-NEW-TARGET">Writing New Devices - target</H1
|
><DIV
|
><DIV
|
CLASS="REFNAMEDIV"
|
CLASS="REFNAMEDIV"
|
><A
|
><A
|
NAME="AEN524"
|
NAME="AEN524"
|
></A
|
></A
|
><H2
|
><H2
|
>Name</H2
|
>Name</H2
|
>Writing New Devices -- extending the synthetic target, target-side</DIV
|
>Writing New Devices -- extending the synthetic target, target-side</DIV
|
><DIV
|
><DIV
|
CLASS="REFSYNOPSISDIV"
|
CLASS="REFSYNOPSISDIV"
|
><A
|
><A
|
NAME="AEN527"><H2
|
NAME="AEN527"><H2
|
>Synopsis</H2
|
>Synopsis</H2
|
><DIV
|
><DIV
|
CLASS="FUNCSYNOPSIS"
|
CLASS="FUNCSYNOPSIS"
|
><A
|
><A
|
NAME="AEN528"><P
|
NAME="AEN528"><P
|
></P
|
></P
|
><TABLE
|
><TABLE
|
BORDER="5"
|
BORDER="5"
|
BGCOLOR="#E0E0F0"
|
BGCOLOR="#E0E0F0"
|
WIDTH="70%"
|
WIDTH="70%"
|
><TR
|
><TR
|
><TD
|
><TD
|
><PRE
|
><PRE
|
CLASS="FUNCSYNOPSISINFO"
|
CLASS="FUNCSYNOPSISINFO"
|
>#include <cyg/hal/hal_io.h
|
>#include <cyg/hal/hal_io.h
|
</PRE
|
</PRE
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>int synth_auxiliary_instantiate</CODE
|
>int synth_auxiliary_instantiate</CODE
|
>(const char* package, const char* version, const char* device, const char* instance, const char* data);</CODE
|
>(const char* package, const char* version, const char* device, const char* instance, const char* data);</CODE
|
></P
|
></P
|
><P
|
><P
|
><CODE
|
><CODE
|
><CODE
|
><CODE
|
CLASS="FUNCDEF"
|
CLASS="FUNCDEF"
|
>void synth_auxiliary_xchgmsg</CODE
|
>void synth_auxiliary_xchgmsg</CODE
|
>(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
|
>(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
|
></P
|
></P
|
><P
|
><P
|
></P
|
></P
|
></DIV
|
></DIV
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="SYNTH-NEW-TARGET-DESCRIPTION"
|
NAME="SYNTH-NEW-TARGET-DESCRIPTION"
|
></A
|
></A
|
><H2
|
><H2
|
>Description</H2
|
>Description</H2
|
><P
|
><P
|
>In some ways writing a device driver for the synthetic target is very
|
>In some ways writing a device driver for the synthetic target is very
|
similar to writing one for a real target. Obviously it has to provide
|
similar to writing one for a real target. Obviously it has to provide
|
the standard interface for that class of device, so for example an
|
the standard interface for that class of device, so for example an
|
ethernet device has to provide <TT
|
ethernet device has to provide <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>can_send</TT
|
>can_send</TT
|
>,
|
>,
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>send</TT
|
>send</TT
|
>, <TT
|
>, <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>recv</TT
|
>recv</TT
|
> and similar
|
> and similar
|
functions. Many devices will involve interrupts, so the driver
|
functions. Many devices will involve interrupts, so the driver
|
contains ISR and DSR functions and will call
|
contains ISR and DSR functions and will call
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_drv_interrupt_create</TT
|
>cyg_drv_interrupt_create</TT
|
>,
|
>,
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_drv_interrupt_acknowledge</TT
|
>cyg_drv_interrupt_acknowledge</TT
|
>, and related
|
>, and related
|
functions.
|
functions.
|
</P
|
</P
|
><P
|
><P
|
>In other ways writing a device driver for the synthetic target is very
|
>In other ways writing a device driver for the synthetic target is very
|
different. Usually the driver will not have any direct access to the
|
different. Usually the driver will not have any direct access to the
|
underlying hardware. In fact for some devices the I/O may not involve
|
underlying hardware. In fact for some devices the I/O may not involve
|
real hardware, instead everything is emulated by widgets on the
|
real hardware, instead everything is emulated by widgets on the
|
graphical display. Therefore the driver cannot just peek and poke
|
graphical display. Therefore the driver cannot just peek and poke
|
device registers, instead it must interact with host-side code by
|
device registers, instead it must interact with host-side code by
|
exchanging message. The synthetic target HAL provides a function
|
exchanging message. The synthetic target HAL provides a function
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>synth_auxiliary_xchgmsg</TT
|
>synth_auxiliary_xchgmsg</TT
|
> for this purpose.
|
> for this purpose.
|
</P
|
</P
|
><P
|
><P
|
>Initialization of a synthetic target device driver is also very
|
>Initialization of a synthetic target device driver is also very
|
different. On real targets the device hardware already exists when the
|
different. On real targets the device hardware already exists when the
|
driver's initialization routine runs. On the synthetic target it is
|
driver's initialization routine runs. On the synthetic target it is
|
first necessary to instantiate the device inside the I/O auxiliary, by
|
first necessary to instantiate the device inside the I/O auxiliary, by
|
a call to <TT
|
a call to <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>synth_auxiliary_instantiate</TT
|
>synth_auxiliary_instantiate</TT
|
>. That
|
>. That
|
function performs a special message exchange with the I/O auxiliary,
|
function performs a special message exchange with the I/O auxiliary,
|
causing it to load a Tcl script for the desired type of device and run
|
causing it to load a Tcl script for the desired type of device and run
|
an instantiation procedure within that script.
|
an instantiation procedure within that script.
|
</P
|
</P
|
><P
|
><P
|
>Use of the I/O auxiliary is optional: if the user does not specify
|
>Use of the I/O auxiliary is optional: if the user does not specify
|
<TT
|
<TT
|
CLASS="OPTION"
|
CLASS="OPTION"
|
>--io</TT
|
>--io</TT
|
> on the command line then the auxiliary will not
|
> on the command line then the auxiliary will not
|
be started and hence most I/O operations will not be possible. Device
|
be started and hence most I/O operations will not be possible. Device
|
drivers should allow for this possibility, for example by just
|
drivers should allow for this possibility, for example by just
|
discarding any data that gets written. The HAL exports a flag
|
discarding any data that gets written. The HAL exports a flag
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>synth_auxiliary_running</TT
|
>synth_auxiliary_running</TT
|
> which should be checked.
|
> which should be checked.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="SYNTH-NEW-TARGET-INSTANTIATE"
|
NAME="SYNTH-NEW-TARGET-INSTANTIATE"
|
></A
|
></A
|
><H2
|
><H2
|
>Instantiating a Device</H2
|
>Instantiating a Device</H2
|
><P
|
><P
|
>Device instantiation should happen during the C++ prioritized static
|
>Device instantiation should happen during the C++ prioritized static
|
constructor phase of system initialization, before control switches to
|
constructor phase of system initialization, before control switches to
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_user_start</TT
|
>cyg_user_start</TT
|
> and general application code. This
|
> and general application code. This
|
ensures that there is a clearly defined point at which the I/O
|
ensures that there is a clearly defined point at which the I/O
|
auxiliary knows that all required devices have been loaded. It can
|
auxiliary knows that all required devices have been loaded. It can
|
then perform various consistency checks and clean-ups, run the user's
|
then perform various consistency checks and clean-ups, run the user's
|
<TT
|
<TT
|
CLASS="FILENAME"
|
CLASS="FILENAME"
|
>mainrc.tcl</TT
|
>mainrc.tcl</TT
|
> script, and make the main window
|
> script, and make the main window
|
visible.
|
visible.
|
</P
|
</P
|
><P
|
><P
|
>For standard devices generic eCos I/O code will call the device
|
>For standard devices generic eCos I/O code will call the device
|
initialization routines at the right time, iterating through the
|
initialization routines at the right time, iterating through the
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>DEVTAB</TT
|
>DEVTAB</TT
|
> table in a static constructor. The same
|
> table in a static constructor. The same
|
holds for network devices and file systems. For more custom devices
|
holds for network devices and file systems. For more custom devices
|
code like the following can be used:
|
code like the following can be used:
|
</P
|
</P
|
><TABLE
|
><TABLE
|
BORDER="5"
|
BORDER="5"
|
BGCOLOR="#E0E0F0"
|
BGCOLOR="#E0E0F0"
|
WIDTH="70%"
|
WIDTH="70%"
|
><TR
|
><TR
|
><TD
|
><TD
|
><PRE
|
><PRE
|
CLASS="PROGRAMLISTING"
|
CLASS="PROGRAMLISTING"
|
>#include <cyg/infra/cyg_type.h>
|
>#include <cyg/infra/cyg_type.h>
|
class mydev_init {
|
class mydev_init {
|
public:
|
public:
|
mydev_init() {
|
mydev_init() {
|
…
|
…
|
}
|
}
|
};
|
};
|
static mydev_init mydev_init_object CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO);</PRE
|
static mydev_init mydev_init_object CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO);</PRE
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
><P
|
><P
|
>Some care has to be taken because the object
|
>Some care has to be taken because the object
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>mydev_init_object</TT
|
>mydev_init_object</TT
|
> will typically not be referenced
|
> will typically not be referenced
|
by other code, and hence may get eliminated at link-time. If the code
|
by other code, and hence may get eliminated at link-time. If the code
|
is part of an eCos package then problems can be avoided by putting the
|
is part of an eCos package then problems can be avoided by putting the
|
relevant file in <TT
|
relevant file in <TT
|
CLASS="FILENAME"
|
CLASS="FILENAME"
|
>libextras.a</TT
|
>libextras.a</TT
|
>:
|
>:
|
</P
|
</P
|
><TABLE
|
><TABLE
|
BORDER="5"
|
BORDER="5"
|
BGCOLOR="#E0E0F0"
|
BGCOLOR="#E0E0F0"
|
WIDTH="70%"
|
WIDTH="70%"
|
><TR
|
><TR
|
><TD
|
><TD
|
><PRE
|
><PRE
|
CLASS="PROGRAMLISTING"
|
CLASS="PROGRAMLISTING"
|
>cdl_package CYGPKG_DEVS_MINE {
|
>cdl_package CYGPKG_DEVS_MINE {
|
…
|
…
|
compile -library=libextras.a init.cxx
|
compile -library=libextras.a init.cxx
|
}</PRE
|
}</PRE
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
><P
|
><P
|
>For devices inside application code the same can be achieved by
|
>For devices inside application code the same can be achieved by
|
linking the relevant module as a <TT
|
linking the relevant module as a <TT
|
CLASS="FILENAME"
|
CLASS="FILENAME"
|
>.o</TT
|
>.o</TT
|
> file rather
|
> file rather
|
than putting it in a <TT
|
than putting it in a <TT
|
CLASS="FILENAME"
|
CLASS="FILENAME"
|
>.a</TT
|
>.a</TT
|
> library.
|
> library.
|
</P
|
</P
|
><P
|
><P
|
>In the device initialization routine the main operation is a call to
|
>In the device initialization routine the main operation is a call to
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>synth_auxiliary_instantiate</TT
|
>synth_auxiliary_instantiate</TT
|
>. This takes five
|
>. This takes five
|
arguments, all of which should be strings:
|
arguments, all of which should be strings:
|
</P
|
</P
|
><P
|
><P
|
></P
|
></P
|
><DIV
|
><DIV
|
CLASS="VARIABLELIST"
|
CLASS="VARIABLELIST"
|
><DL
|
><DL
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>package</TT
|
>package</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>For device drivers which are eCos packages this should be a directory
|
>For device drivers which are eCos packages this should be a directory
|
path relative to the eCos repository, for example
|
path relative to the eCos repository, for example
|
<TT
|
<TT
|
CLASS="LITERAL"
|
CLASS="LITERAL"
|
>devs/eth/synth/ecosynth</TT
|
>devs/eth/synth/ecosynth</TT
|
>. This will allow the I/O
|
>. This will allow the I/O
|
auxiliary to find the various host-side support files for this package
|
auxiliary to find the various host-side support files for this package
|
within the install tree. If the device is application-specific and not
|
within the install tree. If the device is application-specific and not
|
part of an eCos package then a NULL pointer can be used, causing the
|
part of an eCos package then a NULL pointer can be used, causing the
|
I/O auxiliary to search for the support files in the current directory
|
I/O auxiliary to search for the support files in the current directory
|
and then in <TT
|
and then in <TT
|
CLASS="FILENAME"
|
CLASS="FILENAME"
|
>~/.ecos/synth</TT
|
>~/.ecos/synth</TT
|
>
|
>
|
instead.
|
instead.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>version</TT
|
>version</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>For eCos packages this argument should be the version of the package
|
>For eCos packages this argument should be the version of the package
|
that is being used, for example <TT
|
that is being used, for example <TT
|
CLASS="LITERAL"
|
CLASS="LITERAL"
|
>current</TT
|
>current</TT
|
>. A simple
|
>. A simple
|
way to get this version is to use the
|
way to get this version is to use the
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>SYNTH_MAKESTRING</TT
|
>SYNTH_MAKESTRING</TT
|
> macro on the package name.
|
> macro on the package name.
|
If the device is application-specific then a NULL pointer should be
|
If the device is application-specific then a NULL pointer should be
|
used.
|
used.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>device</TT
|
>device</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>This argument specifies the type of device being instantiated, for
|
>This argument specifies the type of device being instantiated, for
|
example <TT
|
example <TT
|
CLASS="LITERAL"
|
CLASS="LITERAL"
|
>ethernet</TT
|
>ethernet</TT
|
>. More specifically the I/O
|
>. More specifically the I/O
|
auxiliary will append a <TT
|
auxiliary will append a <TT
|
CLASS="FILENAME"
|
CLASS="FILENAME"
|
>.tcl</TT
|
>.tcl</TT
|
> suffix, giving
|
> suffix, giving
|
the name of a Tcl script that will handle all I/O requests for the
|
the name of a Tcl script that will handle all I/O requests for the
|
device. If the application requires several instances of a type
|
device. If the application requires several instances of a type
|
of device then the script will only be loaded once, but the script
|
of device then the script will only be loaded once, but the script
|
will contain an instantiation procedure that will be called for each
|
will contain an instantiation procedure that will be called for each
|
device instance.
|
device instance.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>instance</TT
|
>instance</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>If it is possible to have multiple instances of a device then this
|
>If it is possible to have multiple instances of a device then this
|
argument identifies the particular instance, for example
|
argument identifies the particular instance, for example
|
<TT
|
<TT
|
CLASS="LITERAL"
|
CLASS="LITERAL"
|
>eth0</TT
|
>eth0</TT
|
> or <TT
|
> or <TT
|
CLASS="LITERAL"
|
CLASS="LITERAL"
|
>eth1</TT
|
>eth1</TT
|
>. Otherwise a NULL
|
>. Otherwise a NULL
|
pointer can be used.
|
pointer can be used.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>data</TT
|
>data</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>This argument can be used to pass additional initialization data from
|
>This argument can be used to pass additional initialization data from
|
eCos to the host-side support. This is useful for devices where eCos
|
eCos to the host-side support. This is useful for devices where eCos
|
configury must control certain aspects of the device, rather than
|
configury must control certain aspects of the device, rather than
|
host-side configury such as the target definition file, because eCos
|
host-side configury such as the target definition file, because eCos
|
has compile-time dependencies on some or all of the relevant options.
|
has compile-time dependencies on some or all of the relevant options.
|
An example might be an emulated frame buffer where eCos has been
|
An example might be an emulated frame buffer where eCos has been
|
statically configured for a particular screen size, orientation and
|
statically configured for a particular screen size, orientation and
|
depth. There is no fixed format for this string, it will be
|
depth. There is no fixed format for this string, it will be
|
interpreted only by the device-specific host-side Tcl script. However
|
interpreted only by the device-specific host-side Tcl script. However
|
the string length should be limited to a couple of hundred bytes to
|
the string length should be limited to a couple of hundred bytes to
|
avoid possible buffer overflow problems.
|
avoid possible buffer overflow problems.
|
</P
|
</P
|
></DD
|
></DD
|
></DL
|
></DL
|
></DIV
|
></DIV
|
><P
|
><P
|
>Typical usage would look like:
|
>Typical usage would look like:
|
</P
|
</P
|
><TABLE
|
><TABLE
|
BORDER="5"
|
BORDER="5"
|
BGCOLOR="#E0E0F0"
|
BGCOLOR="#E0E0F0"
|
WIDTH="70%"
|
WIDTH="70%"
|
><TR
|
><TR
|
><TD
|
><TD
|
><PRE
|
><PRE
|
CLASS="PROGRAMLISTING"
|
CLASS="PROGRAMLISTING"
|
> if (!synth_auxiliary_running) {
|
> if (!synth_auxiliary_running) {
|
return;
|
return;
|
}
|
}
|
id = synth_auxiliary_instantiate("devs/eth/synth/ecosynth",
|
id = synth_auxiliary_instantiate("devs/eth/synth/ecosynth",
|
SYNTH_MAKESTRING(CYGPKG_DEVS_ETH_ECOSYNTH),
|
SYNTH_MAKESTRING(CYGPKG_DEVS_ETH_ECOSYNTH),
|
"ethernet",
|
"ethernet",
|
"eth0",
|
"eth0",
|
(const char*) 0);</PRE
|
(const char*) 0);</PRE
|
></TD
|
></TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
><P
|
><P
|
>The return value will be a device identifier which can be used for
|
>The return value will be a device identifier which can be used for
|
subsequent calls to <TT
|
subsequent calls to <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>synth_auxiliary_xchgmsg</TT
|
>synth_auxiliary_xchgmsg</TT
|
>. If
|
>. If
|
the device could not be instantiated then <TT
|
the device could not be instantiated then <TT
|
CLASS="LITERAL"
|
CLASS="LITERAL"
|
>-1</TT
|
>-1</TT
|
> will
|
> will
|
be returned. It is the responsibility of the host-side software to
|
be returned. It is the responsibility of the host-side software to
|
issue suitable diagnostics explaining what went wrong, so normally the
|
issue suitable diagnostics explaining what went wrong, so normally the
|
target-side code should fail silently.
|
target-side code should fail silently.
|
</P
|
</P
|
><P
|
><P
|
>Once the desired device has been instantiated, often it will be
|
>Once the desired device has been instantiated, often it will be
|
necessary to do some additional initialization by a message exchange.
|
necessary to do some additional initialization by a message exchange.
|
For example an ethernet device might need information from the
|
For example an ethernet device might need information from the
|
host-side about the MAC address, the <A
|
host-side about the MAC address, the <A
|
HREF="synth-new-target.html#SYNTH-NEW-TARGET-INTERRUPTS"
|
HREF="synth-new-target.html#SYNTH-NEW-TARGET-INTERRUPTS"
|
>interrupt vector</A
|
>interrupt vector</A
|
>, and
|
>, and
|
whether or not multicasting is supported.
|
whether or not multicasting is supported.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="SYNTH-NEW-TARGET-XCHGMSG"
|
NAME="SYNTH-NEW-TARGET-XCHGMSG"
|
></A
|
></A
|
><H2
|
><H2
|
>Communicating with a Device</H2
|
>Communicating with a Device</H2
|
><P
|
><P
|
>Once a device has been instantiated it is possible to perform I/O by
|
>Once a device has been instantiated it is possible to perform I/O by
|
sending messages to the appropriate Tcl script running inside the
|
sending messages to the appropriate Tcl script running inside the
|
auxiliary, and optionally getting back replies. I/O operations are
|
auxiliary, and optionally getting back replies. I/O operations are
|
always initiated by the eCos target-side, it is not possible for the
|
always initiated by the eCos target-side, it is not possible for the
|
host-side software to initiate data transfers. However the host-side
|
host-side software to initiate data transfers. However the host-side
|
can raise interrupts, and the interrupt handler inside the target can
|
can raise interrupts, and the interrupt handler inside the target can
|
then exchange one or more messages with the host.
|
then exchange one or more messages with the host.
|
</P
|
</P
|
><P
|
><P
|
>There is a single function to perform I/O operations,
|
>There is a single function to perform I/O operations,
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>synth_auxiliary_xchgmsg</TT
|
>synth_auxiliary_xchgmsg</TT
|
>. This takes the following
|
>. This takes the following
|
arguments:
|
arguments:
|
</P
|
</P
|
><P
|
><P
|
></P
|
></P
|
><DIV
|
><DIV
|
CLASS="VARIABLELIST"
|
CLASS="VARIABLELIST"
|
><DL
|
><DL
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>device_id</TT
|
>device_id</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>This should be one of the identifiers returned by a previous
|
>This should be one of the identifiers returned by a previous
|
call to <TT
|
call to <TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>synth_auxiliary_instantiate</TT
|
>synth_auxiliary_instantiate</TT
|
>, specifying the
|
>, specifying the
|
particular device which should perform some I/O.
|
particular device which should perform some I/O.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>request</TT
|
>request</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>Request are just signed 32-bit integers that identify the particular
|
>Request are just signed 32-bit integers that identify the particular
|
I/O operation being requested. There is no fixed set of codes, instead
|
I/O operation being requested. There is no fixed set of codes, instead
|
each type of device can define its own.
|
each type of device can define its own.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg1</TT
|
>arg1</TT
|
>, <TT
|
>, <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg2</TT
|
>arg2</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>For some requests it is convenient to pass one or two additional
|
>For some requests it is convenient to pass one or two additional
|
parameters alongside the request code. For example an ethernet device
|
parameters alongside the request code. For example an ethernet device
|
could define a multicast-all request, with <TT
|
could define a multicast-all request, with <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg1</TT
|
>arg1</TT
|
>
|
>
|
controlling whether this mode should be enabled or disabled. Both
|
controlling whether this mode should be enabled or disabled. Both
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg1</TT
|
>arg1</TT
|
> and <TT
|
> and <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg2</TT
|
>arg2</TT
|
> should be signed
|
> should be signed
|
32-bit integers, and their values are interpreted only by the
|
32-bit integers, and their values are interpreted only by the
|
device-specific Tcl script.
|
device-specific Tcl script.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>txdata</TT
|
>txdata</TT
|
>, <TT
|
>, <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>txlen</TT
|
>txlen</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>Some I/O operations may involve sending additional data, for example
|
>Some I/O operations may involve sending additional data, for example
|
an ethernet packet. Alternatively a control operation may require many
|
an ethernet packet. Alternatively a control operation may require many
|
more parameters than can easily be encoded in <TT
|
more parameters than can easily be encoded in <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg1</TT
|
>arg1</TT
|
>
|
>
|
and <TT
|
and <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg2</TT
|
>arg2</TT
|
>, so those parameters have to be placed in
|
>, so those parameters have to be placed in
|
a suitable buffer and extracted at the other end.
|
a suitable buffer and extracted at the other end.
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>txdata</TT
|
>txdata</TT
|
> is an arbitrary buffer of
|
> is an arbitrary buffer of
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>txlen</TT
|
>txlen</TT
|
> bytes that should be sent to the host-side.
|
> bytes that should be sent to the host-side.
|
There is no specific upper bound on the number of bytes that can be
|
There is no specific upper bound on the number of bytes that can be
|
sent, but usually it is a good idea to allocate the transmit buffer
|
sent, but usually it is a good idea to allocate the transmit buffer
|
statically and keep transfers down to at most several kilobytes.
|
statically and keep transfers down to at most several kilobytes.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>reply</TT
|
>reply</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>If the host-side is expected to send a reply message then
|
>If the host-side is expected to send a reply message then
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>reply</TT
|
>reply</TT
|
> should be a pointer to an integer variable
|
> should be a pointer to an integer variable
|
and will be updated with a reply code, a simple 32-bit integer. The
|
and will be updated with a reply code, a simple 32-bit integer. The
|
synthetic target HAL code assumes that the host-side and target-side
|
synthetic target HAL code assumes that the host-side and target-side
|
agree on the protocol being used: if the host-side will not send a
|
agree on the protocol being used: if the host-side will not send a
|
reply to this message then the <TT
|
reply to this message then the <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>reply</TT
|
>reply</TT
|
> argument
|
> argument
|
should be a NULL pointer; otherwise the host-side must always send
|
should be a NULL pointer; otherwise the host-side must always send
|
a reply code and the <TT
|
a reply code and the <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>reply</TT
|
>reply</TT
|
> argument must be valid.
|
> argument must be valid.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>rxdata</TT
|
>rxdata</TT
|
>, <TT
|
>, <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>rxlen</TT
|
>rxlen</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>Some operations may involve additional data coming from the host-side,
|
>Some operations may involve additional data coming from the host-side,
|
for example an incoming ethernet packet. <TT
|
for example an incoming ethernet packet. <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>rxdata</TT
|
>rxdata</TT
|
>
|
>
|
should be a suitably-sized buffer, and <TT
|
should be a suitably-sized buffer, and <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>rxlen</TT
|
>rxlen</TT
|
> a
|
> a
|
pointer to an integer variable that will end up containing the number
|
pointer to an integer variable that will end up containing the number
|
of bytes that were actually received. These arguments will only be
|
of bytes that were actually received. These arguments will only be
|
used if the host-side is expected to send a reply and hence the
|
used if the host-side is expected to send a reply and hence the
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>reply</TT
|
>reply</TT
|
> argument was not NULL.
|
> argument was not NULL.
|
</P
|
</P
|
></DD
|
></DD
|
><DT
|
><DT
|
><TT
|
><TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>max_rxlen</TT
|
>max_rxlen</TT
|
></DT
|
></DT
|
><DD
|
><DD
|
><P
|
><P
|
>If a reply to this message is expected and that reply may involve
|
>If a reply to this message is expected and that reply may involve
|
additional data, <TT
|
additional data, <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>max_rxlen</TT
|
>max_rxlen</TT
|
> limits the size of that
|
> limits the size of that
|
reply. In other words, it corresponds to the size of the
|
reply. In other words, it corresponds to the size of the
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>rxdata</TT
|
>rxdata</TT
|
> buffer.
|
> buffer.
|
</P
|
</P
|
></DD
|
></DD
|
></DL
|
></DL
|
></DIV
|
></DIV
|
><P
|
><P
|
>Most I/O operations involve only some of the arguments. For example
|
>Most I/O operations involve only some of the arguments. For example
|
transmitting an ethernet packet would use the
|
transmitting an ethernet packet would use the
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>request</TT
|
>request</TT
|
>, <TT
|
>, <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>txdata</TT
|
>txdata</TT
|
> and
|
> and
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>txlen</TT
|
>txlen</TT
|
> fields (in addition to
|
> fields (in addition to
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>device_id</TT
|
>device_id</TT
|
> which is always required), but would not
|
> which is always required), but would not
|
involve <TT
|
involve <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg1</TT
|
>arg1</TT
|
> or <TT
|
> or <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg2</TT
|
>arg2</TT
|
> and no
|
> and no
|
reply would be expected. Receiving an ethernet packet would involve
|
reply would be expected. Receiving an ethernet packet would involve
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>request</TT
|
>request</TT
|
>, <TT
|
>, <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>rxdata</TT
|
>rxdata</TT
|
>,
|
>,
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>rxlen</TT
|
>rxlen</TT
|
> and <TT
|
> and <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>max_rxlen</TT
|
>max_rxlen</TT
|
>; in addition
|
>; in addition
|
<TT
|
<TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>reply</TT
|
>reply</TT
|
> is needed to get any reply from the host-side
|
> is needed to get any reply from the host-side
|
at all, and could be used to indicate whether or not any more packets
|
at all, and could be used to indicate whether or not any more packets
|
are buffered up. A control operation such as enabling multicast mode
|
are buffered up. A control operation such as enabling multicast mode
|
would involve <TT
|
would involve <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>request</TT
|
>request</TT
|
> and <TT
|
> and <TT
|
CLASS="VARNAME"
|
CLASS="VARNAME"
|
>arg1</TT
|
>arg1</TT
|
>,
|
>,
|
but none of the remaining arguments.
|
but none of the remaining arguments.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="REFSECT1"
|
CLASS="REFSECT1"
|
><A
|
><A
|
NAME="SYNTH-NEW-TARGET-INTERRUPTS"
|
NAME="SYNTH-NEW-TARGET-INTERRUPTS"
|
></A
|
></A
|
><H2
|
><H2
|
>Interrupt Handling</H2
|
>Interrupt Handling</H2
|
><P
|
><P
|
>Interrupt handling in the synthetic target is much the same as on a
|
>Interrupt handling in the synthetic target is much the same as on a
|
real target. An interrupt object is created using
|
real target. An interrupt object is created using
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>cyg_drv_interrupt_create</TT
|
>cyg_drv_interrupt_create</TT
|
>, attached, and unmasked.
|
>, attached, and unmasked.
|
The emulated device - in other words the Tcl script running inside the
|
The emulated device - in other words the Tcl script running inside the
|
I/O auxiliary - can raise an interrupt. Subject to interrupts being
|
I/O auxiliary - can raise an interrupt. Subject to interrupts being
|
disabled and the appropriate vector being masked, the system will
|
disabled and the appropriate vector being masked, the system will
|
invoke the specified ISR function. The synthetic target HAL
|
invoke the specified ISR function. The synthetic target HAL
|
implementation does have some limitations: there is no support for
|
implementation does have some limitations: there is no support for
|
nested interrupts, interrupt priorities, or a separate interrupt
|
nested interrupts, interrupt priorities, or a separate interrupt
|
stack. Supporting those might be appropriate when targetting a
|
stack. Supporting those might be appropriate when targetting a
|
simulator that attempts to model real hardware accurately, but not for
|
simulator that attempts to model real hardware accurately, but not for
|
the simple emulation provided by the synthetic target.
|
the simple emulation provided by the synthetic target.
|
</P
|
</P
|
><P
|
><P
|
>Of course the actual implementation of the ISR and DSR functions will
|
>Of course the actual implementation of the ISR and DSR functions will
|
be rather different for a synthetic target device driver. For real
|
be rather different for a synthetic target device driver. For real
|
hardware the device driver will interact with the device by reading
|
hardware the device driver will interact with the device by reading
|
and writing device registers, managing DMA engines, and the like. A
|
and writing device registers, managing DMA engines, and the like. A
|
synthetic target driver will instead call
|
synthetic target driver will instead call
|
<TT
|
<TT
|
CLASS="FUNCTION"
|
CLASS="FUNCTION"
|
>synth_auxiliary_xchgmsg</TT
|
>synth_auxiliary_xchgmsg</TT
|
> to perform the I/O
|
> to perform the I/O
|
operations.
|
operations.
|
</P
|
</P
|
><P
|
><P
|
>There is one other significant difference between interrupt handling
|
>There is one other significant difference between interrupt handling
|
on the synthetic target and on real hardware. Usually the eCos code
|
on the synthetic target and on real hardware. Usually the eCos code
|
will know which interrupt vectors are used for which devices. That
|
will know which interrupt vectors are used for which devices. That
|
information is fixed when the target hardware is designed. With the
|
information is fixed when the target hardware is designed. With the
|
synthetic target interrupt vectors are assigned to devices on the host
|
synthetic target interrupt vectors are assigned to devices on the host
|
side, either via the target definition file or dynamically when the
|
side, either via the target definition file or dynamically when the
|
device is instantiated. Therefore the initialization code for a
|
device is instantiated. Therefore the initialization code for a
|
target-side device driver will need to request interrupt vector
|
target-side device driver will need to request interrupt vector
|
information from the host-side, via a message exchange. Such interrupt
|
information from the host-side, via a message exchange. Such interrupt
|
vectors will be in the range 1 to 31 inclusive, with interrupt 0 being
|
vectors will be in the range 1 to 31 inclusive, with interrupt 0 being
|
reserved for the real-time clock.
|
reserved for the real-time clock.
|
</P
|
</P
|
></DIV
|
></DIV
|
><DIV
|
><DIV
|
CLASS="NAVFOOTER"
|
CLASS="NAVFOOTER"
|
><HR
|
><HR
|
ALIGN="LEFT"
|
ALIGN="LEFT"
|
WIDTH="100%"><TABLE
|
WIDTH="100%"><TABLE
|
SUMMARY="Footer navigation table"
|
SUMMARY="Footer navigation table"
|
WIDTH="100%"
|
WIDTH="100%"
|
BORDER="0"
|
BORDER="0"
|
CELLPADDING="0"
|
CELLPADDING="0"
|
CELLSPACING="0"
|
CELLSPACING="0"
|
><TR
|
><TR
|
><TD
|
><TD
|
WIDTH="33%"
|
WIDTH="33%"
|
ALIGN="left"
|
ALIGN="left"
|
VALIGN="top"
|
VALIGN="top"
|
><A
|
><A
|
HREF="synth-syscalls.html"
|
HREF="synth-syscalls.html"
|
ACCESSKEY="P"
|
ACCESSKEY="P"
|
>Prev</A
|
>Prev</A
|
></TD
|
></TD
|
><TD
|
><TD
|
WIDTH="34%"
|
WIDTH="34%"
|
ALIGN="center"
|
ALIGN="center"
|
VALIGN="top"
|
VALIGN="top"
|
><A
|
><A
|
HREF="hal-synth-arch.html"
|
HREF="hal-synth-arch.html"
|
ACCESSKEY="H"
|
ACCESSKEY="H"
|
>Home</A
|
>Home</A
|
></TD
|
></TD
|
><TD
|
><TD
|
WIDTH="33%"
|
WIDTH="33%"
|
ALIGN="right"
|
ALIGN="right"
|
VALIGN="top"
|
VALIGN="top"
|
><A
|
><A
|
HREF="synth-new-host.html"
|
HREF="synth-new-host.html"
|
ACCESSKEY="N"
|
ACCESSKEY="N"
|
>Next</A
|
>Next</A
|
></TD
|
></TD
|
></TR
|
></TR
|
><TR
|
><TR
|
><TD
|
><TD
|
WIDTH="33%"
|
WIDTH="33%"
|
ALIGN="left"
|
ALIGN="left"
|
VALIGN="top"
|
VALIGN="top"
|
>System Calls</TD
|
>System Calls</TD
|
><TD
|
><TD
|
WIDTH="34%"
|
WIDTH="34%"
|
ALIGN="center"
|
ALIGN="center"
|
VALIGN="top"
|
VALIGN="top"
|
> </TD
|
> </TD
|
><TD
|
><TD
|
WIDTH="33%"
|
WIDTH="33%"
|
ALIGN="right"
|
ALIGN="right"
|
VALIGN="top"
|
VALIGN="top"
|
>Writing New Devices - host</TD
|
>Writing New Devices - host</TD
|
></TR
|
></TR
|
></TABLE
|
></TABLE
|
></DIV
|
></DIV
|
></BODY
|
></BODY
|
></HTML
|
></HTML
|
|
|