📄 synth-new-host.html
字号:
CLASS="LITERAL"
>eth0</TT
>. This is not actually used
internally, but can be accessed by user-initialization scripts that
provide some sort of interrupt monitoring facility (typically via the
<TT
CLASS="LITERAL"
>interrupt</TT
> <A
HREF="synth-new-host.html#SYNTH-NEW-HOST-HOOKS"
>hook</A
>). It is possible for a
single device to allocate multiple interrupt vectors, but the
synthetic target supports a maximum of 32 such vectors.
</P
><P
><B
CLASS="COMMAND"
>synth::interrupt_get_max</B
> returns the highest
interrupt vector that has been allocated, or <TT
CLASS="LITERAL"
>0</TT
> if
there have been no calls to
<B
CLASS="COMMAND"
>synth::interrupt_allocate</B
>.
<B
CLASS="COMMAND"
>synth::interrupt_get_devicename</B
> returns the string
that was passed to <B
CLASS="COMMAND"
>synth::interrupt_allocate</B
> when
the vector was allocated.
</P
><P
><B
CLASS="COMMAND"
>synth::interrupt_raise</B
> can be called any time after
initialization. The argument should be the vector returned by
<B
CLASS="COMMAND"
>synth::interrupt_allocate</B
> for this device. It will
activate the normal eCos interrupt handling mechanism so, subject to
interrupts being enabled and this particular interrupt not being
masked out, the appropriate ISR will run.
</P
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
>At this time it is not possible for a device to allocate a specific
interrupt vector. The order in which interrupt vectors are assigned to
devices effectively depends on the order in which the eCos devices get
initialized, and that may change if the eCos application is rebuilt. A
future extension may allow devices to allocate specific vectors, thus
making things more deterministic. However that will introduce new
problems, in particular the code will have to start worrying about
requests for vectors that have already been allocated.
</P
></BLOCKQUOTE
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="SYNTH-NEW-HOST-ARGS"
></A
><H2
>Flags and Command Line Arguments</H2
><P
>The generic I/O auxiliary code will process the standard command line
arguments, and will set various flag variables accordingly. Some of
these should be checked by device-specific scripts.
</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
><TT
CLASS="VARNAME"
>synth::flag_gui</TT
></DT
><DD
><P
>This is set when the I/O auxiliary is operating in graphical mode
rather than text mode. Some functionality such as filters and the GUI
layout are only available in graphical mode.
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> if { $synth::flag_gui } {
…
}</PRE
></TD
></TR
></TABLE
></DD
><DT
><TT
CLASS="VARNAME"
>synth::flag_verbose</TT
></DT
><DD
><P
>The user has requested additional information during startup. Each
device driver can decide how much additional information, if any,
should be produced.
</P
></DD
><DT
><TT
CLASS="VARNAME"
>synth::flag_keep_going</TT
></DT
><DD
><P
>The user has specified <TT
CLASS="OPTION"
>-k</TT
> or
<TT
CLASS="OPTION"
>--keep-going</TT
>, so even if an error occurs the I/O
auxiliary and the various device driver scripts should continue running
if at all possible. Diagnostics should still be generated.
</P
></DD
></DL
></DIV
><P
>Some scripts may want to support additional command line arguments.
This facility should be used with care since there is no way to
prevent two different scripts from trying to use the same argument.
The following Tcl procedures are available:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>synth::argv_defined <name>
synth::argv_get_value <name></PRE
></TD
></TR
></TABLE
><P
><B
CLASS="COMMAND"
>synth::argv_defined</B
> returns a boolean to indicate
whether or not a particular argument is present. If the argument is
the name part of a name/value pair, an <TT
CLASS="LITERAL"
>=</TT
> character
should be appended. Typical uses might be:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> if { [synth::argv_defined "-o13"] } {
…
}
if { [synth::argv_defined "-mark="] } {
…
}</PRE
></TD
></TR
></TABLE
><P
>The first call checks for a flag <TT
CLASS="LITERAL"
>-o13</TT
> or
<TT
CLASS="LITERAL"
>--o13</TT
> - the code treats options with single and
double hyphens interchangeably. The second call checks for an argument
of the form <TT
CLASS="LITERAL"
>-mark=<value></TT
> or a pair of
arguments <TT
CLASS="LITERAL"
>-mark <value></TT
>. The value part of a
name/value pair can be obtained using
<B
CLASS="COMMAND"
>synth::argv_get_value</B
>;
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> variable speed 1
if { [synth::argv_defined "-mark="] } {
set mark [synth::argv_get_value "-mark="]
if { ![string is integer $mark] || ($mark < 1) || ($mark > 9) } {
<issue diagnostic>
} else {
set speed $mark
}
}</PRE
></TD
></TR
></TABLE
><P
><B
CLASS="COMMAND"
>synth::argv_get_value</B
> should only be used after a
successful call to <B
CLASS="COMMAND"
>synth::argv_defined</B
>.
At present there is no support for some advanced forms of command line
argument processing. For example it is not possible to repeat a
certain option such as <TT
CLASS="OPTION"
>-v</TT
> or
<TT
CLASS="OPTION"
>--verbose</TT
>, with each occurrence increasing the level
of verbosity.
</P
><P
>If a script is going to have its own set of command-line arguments
then it should give appropriate details if the user specifies
<TT
CLASS="OPTION"
>--help</TT
>. This involves a hook function:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>namespace eval my_device {
proc help_hook { } {
puts " -o13 : activate the omega 13 device"
puts " -mark <speed> : set speed. Valid values are 1 to 9."
}
synth::hook_add "help" my_device::help_hook
}</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="SYNTH-NEW-HOST-TDF"
></A
><H2
>The Target Definition File</H2
><P
>Most device scripts will want to check entries in the target
definition file for run-time configuration information. The Tcl
procedures for this are as follows:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>synth::tdf_has_device <name>
synth::tdf_get_devices
synth::tdf_has_option <devname> <option>
synth::tdf_get_option <devname> <option>
synth::tdf_get_options <devname> <option>
synth::tdf_get_all_options <devname></PRE
></TD
></TR
></TABLE
><P
><B
CLASS="COMMAND"
>synth::tdf_has_device</B
> can be used to check whether
or not the target definition file had an entry
<TT
CLASS="LITERAL"
>synth_device <name></TT
>. Usually the name
will match the type of device, so the
<TT
CLASS="FILENAME"
>console.tcl</TT
> script will look for a target
definition file entry <TT
CLASS="LITERAL"
>console</TT
>.
<B
CLASS="COMMAND"
>synth::tdf_get_devices</B
> returns a list of all
device entries in the target definition file.
</P
><P
>Once it is known that the target definition file has an entry for a
certain device, it is possible to check for options within the entry.
<B
CLASS="COMMAND"
>synth::tdf_has_option</B
> just checks for the presence,
returning a boolean:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> if { [synth::tdf_has_option "console" "appearance"] } {
…
}</PRE
></TD
></TR
></TABLE
><P
><B
CLASS="COMMAND"
>synth::tdf_get_option</B
> returns a list of all the
arguments for a given option. For example, if the target definition
file contains an entry:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>synth_device console {
appearance -foreground white -background black
filter trace {^TRACE:.*} -foreground HotPink1 -hide 1
filter xyzzy {.*xyzzy.*} -foreground PapayaWhip
}</PRE
></TD
></TR
></TABLE
><P
>A call
<B
CLASS="COMMAND"
>synth::tdf_get_option console appearance</B
>
will return the list <TT
CLASS="LITERAL"
>{-foreground white -background
black}</TT
>. This list can be manipulated using standard Tcl routines
such as <B
CLASS="COMMAND"
>llength</B
> and <B
CLASS="COMMAND"
>lindex</B
>. Some
options can occur multiple times in one entry, for example
<TT
CLASS="OPTION"
>filter</TT
> in the <TT
CLASS="LITERAL"
>console</TT
> entry.
<B
CLASS="COMMAND"
>synth::tdf_get_options</B
> returns a list of lists,
with one entry for each option occurrence.
<B
CLASS="COMMAND"
>synth::tdf_get_all_options</B
> returns a list of lists
of all options. This time each entry will include the option name as
well.
</P
><P
>The I/O auxiliary will not issue warnings about entries in the target
definition file for devices which were not loaded, unless the
<TT
CLASS="OPTION"
>-v</TT
> or <TT
CLASS="OPTION"
>--verbose</TT
> command line
argument was used. This makes it easier to use a single target
definition file for different applications. However the auxiliary will
issue warnings about options within an entry that were ignored,
because often these indicate a typing mistake of some sort. Hence a
script should always call <B
CLASS="COMMAND"
>synth::tdf_has_option</B
>,
<B
CLASS="COMMAND"
>synth:;tdf_get_option</B
> or
<B
CLASS="COMMAND"
>synth::tdf_get_options</B
> for all valid options, even
if some of the options preclude the use of others.
</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="SYNTH-NEW-HOST-HOOKS"
></A
><H2
>Hooks</H2
><P
>Some scripts may want to take action when particular events occur, for
example when the eCos application has exited and there is no need for
further I/O. This is supported using hooks:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>namespace eval my_device {
…
proc handle_ecos_exit { arg_list } {
…
}
synth::hook_add "ecos_exit" my_device::handle_ecos_exit
}</PRE
></TD
></TR
></TABLE
><P
>It is possible for device scripts to add their own hooks and call all
functions registered for those hooks. A typical use for this is by
user initialization scripts that want to monitor some types of I/O.
The available Tcl procedures for manipulating hooks are:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>synth::hook_define <name>
synth::hook_defined <name>
synth::hook_add <name> <function>
synth::hook_call <name> <args></PRE
></TD
></TR
></TABLE
><P
><B
CLASS="COMMAND"
>synth::hook_define</B
> creates a new hook with the
specified name. This hook must not already exist.
<B
CLASS="COMMAND"
>synth::hook_defined</B
> can be used to check for the
existence of a hook. <B
CLASS="COMMAND"
>synth::hook_add</B
> allows other
scripts to register a callback function for this hook, and
<B
CLASS="COMMAND"
>synth::hook_call</B
> allows the owner script to invoke
all such callback functions. A hook must already be defined before a
callback can be attached. Therefore typically device scripts will only
use standard hooks and their own hooks, not hooks created by some
other device, because the order of device initialization is not
sufficiently defined. User scripts run from
<TT
CLASS="FILENAME"
>mainrc.tcl</TT
> can use any hooks that have been
defined.
</P
><P
><B
CLASS="COMMAND"
>synth::hook_call</B
> takes an arbitrary list of
arguments, for example:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> synth::hook_call "ethernet_rx" "eth0" $packet</PRE
></TD
></TR
></TABLE
><P
>The callback function will always be invoked with a single argument,
a list of the arguments that were passed to
<B
CLASS="COMMAND"
>synth::hook_call</B
>:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> proc rx_callback { arg_list } {
set device [lindex $arg_list 0]
set packet [lindex $arg_list 1]
}</PRE
></TD
></TR
></TABLE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -