📄 ecosynth.tcl
字号:
# {{{ Banner # ============================================================================# # ecosynth.tcl# # The eCos synthetic target I/O auxiliary# # ============================================================================# ####COPYRIGHTBEGIN##### # ----------------------------------------------------------------------------# Copyright (C) 2002 Bart Veer# # This file is part of the eCos host tools.# # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation; either version 2 of the License, or (at your option) # any later version.# # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details.# # You should have received a copy of the GNU General Public License along with# this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.# # ----------------------------------------------------------------------------# # ####COPYRIGHTEND##### ============================================================================# #####DESCRIPTIONBEGIN##### # Author(s): bartv# Contact(s): bartv# Date: 2002/08/05# Version: 0.01# Description:# The main script for the eCos synthetic target auxiliary. This should# only ever be invoked from inside ecosynth.# # ####DESCRIPTIONEND##### ============================================================================# }}}# {{{ Overview # When an eCos synthetic target application runs it will usually# fork/execve an auxiliary program, ecosynth, to provide certain# I/O functionality. This happens as part of hardware initialization.## The ecosynth executable in turn runs this ecosynth.tcl script which# either does most of the real work or delegates it to other scripts.# Those other scripts may in turn exec other programs to perform any# I/O operations that cannot easily be done at the Tcl level. For# example performing low-level ethernet operations generally requires# working at the C level or equivalent, so a separate executable would# be appropriate. The ecosynth executable will transfer control to# this script after the appinit() call, which should have performed# certain initialization steps.## 1) the Tcl interpreter will be fully initialized.## 2) usually Tk will have been loaded and initialized as well. This# can be suppressed using a command-line option -nw.## 3) there will be a namespace synth:: for use by ecosynth.tcl# Auxiliary scripts are expected to use their own namespace# where possible.## 4) there will be two channels synth::_channel_from_app and# synth::_channel_to_app. These correspond to a pipe between# the eCos application and the auxiliary. The application will# send requests using this pipe and expect replies. I/O# operations are always initiated by a request from the# application, but the auxiliary can raise an interrupt via# the SIGIO signal.## Other standard channels stdin, stdout and stderr will have# been inherited from the eCos application.## 5) some Tcl commands implemented in C will have been added to the# interpreter. The most notable is synth::_send_SIGIO, used to# raise an interrupt within the application. ## 6) similarly some variables will have been added to the interpreter.### Configuring everything can get somewhat complicated. It is the eCos# application that knows what I/O facilities within the auxiliary it# wants to access, but it may not know all the details. The eCos# component architecture makes things a bit more complicated still,# generic code such as this ecosynth.tcl script has no way of knowing# what I/O facilities might be provided by some package or other.## For example, a target-side ethernet driver may want to send outgoing# ethernet packets to some script or program on the host and receive# incoming ethernet packets. However it does not necessarily know what# the host-side should do with those ethernet packets, e.g. use a# spare Linux ethernet device, use the Linux kernel's ethertap# facility, ... Although that kind of information could be handled by# target-side configury, host-side configuration files will often be# more appropriate. Specifically it would allow a single eCos# synthetic target application to run in a variety of environments,# using different ways to provide the I/O, with no need to do any# reconfiguring or rebuilding of the target side.### The basic approach that is taken is:## 1) the eCos application tells the auxiliary what I/O facilities# it is interested in. This should happen as a result# of static constructors or of device driver initialization# routines. The application has no control over the implementation# of the I/O facilities, it just expects something on the other# end to respond sensibly to requests.## For example, a synthetic target ethernet driver will supply# an initialization routine via its NETDEVTAB_ENTRY. This# routine will send a request to the auxiliary asking for a# device of type ethernet, id "eth0", provided by# CYGPKG_DEVS_ETH_ECOSYNTH, version current. The auxiliary will# now attempt to load a suitable Tcl script ethernet.tcl from a# location determined using the package name and version.# # 2) there is a primary target definition file which can be# specified as the final argument on the command line, with# "default" being the default value. The code will look for# this file with or without a .tdf extension, first in the# current directory, then in ~/.ecos/synth/. This file is# actually a Tcl script that gets executed in the current# interpreter. However typically it will only contain# entries such as:## synth_device eth0 {# ...# }## 3) There are additional optional configuration files# ~/.ecos/synth/initrc.tcl and ~/.ecos/synth/mainrc.tcl which can# be used for further customization. initrc.tcl will get run# early on, mainrc.tcl will get run once initialization is# complete. Specifically the target-side code will send an# appropriate request after invoking all the static constructors.# At this time the auxiliary will run mainrc.tcl, and in addition# it may issue warnings about unused arguments etc.## 4) there may also be separate configuration files for GUI# preferences etc. These are distinct from the initrc and# mainrc files in that they are generated rather than# hand-written.# }}}# {{{ Basic initialization # ----------------------------------------------------------------------------# There should be two channels corresponding to the pipe between the# eCos application and the auxiliary. These should be configured# appropriately. If either channel does not exist then that is a# very good indication that the system is not properly initialized,# i.e. that this script is not being run by the ecosynth executable# and by implication that no eCos application is involved.if {([info exists synth::_channel_to_app] == 0) || ([info exists synth::_channel_from_app] == 0) || ([info exists synth::_ecosynth_version] == 0) || ([info exists synth::_ppid] == 0) || ([info exists synth::_ecosynth_repository] == 0) || ([info exists synth::_ecosynth_libexecdir] == 0) || ([info exists synth::_ecosynth_package_dir] == 0) || ([info exists synth::_ecosynth_package_version] == 0) || ([info exists synth::_ecosynth_package_install] == 0) || ([info commands synth::_send_SIGIO] == "") || ([info commands synth::_send_SIGKILL] == "") } { puts stderr "ecosynth.tcl: the current interpreter has not been properly initialized." puts stderr " This script should only be invoked by the ecosynth executable when" puts stderr " an eCos synthetic target application is run." exit 1}# Is the script currently being executed the most recent version?# This check should only happen if an environment variable# ECOSYNTH_DEVEL is set, because the installed tools may have come# from somewhere other than the current repository.if { [info exists ::env(ECOSYNTH_DEVEL)] } { set _orig_name [file join $synth::_ecosynth_repository $synth::_ecosynth_package_dir $synth::_ecosynth_package_version \ "host" [file tail [info script]]] if { [file exists $_orig_name] && [file readable $_orig_name] && ($_orig_name != [info script]) } { if { [file mtime $_orig_name] >= [file mtime [info script]] } { puts "$_orig_name is more recent than install: executing that." source $_orig_name return } } unset _orig_name}fconfigure $synth::_channel_to_app -buffering nonefconfigure $synth::_channel_from_app -encoding binaryfconfigure $synth::_channel_to_app -encoding binaryfconfigure $synth::_channel_from_app -translation binaryfconfigure $synth::_channel_to_app -translation binary# Define additional globals and procedures inside the synth:: namespace.# Variables and functions that begin with an _ are considered internal# and should not be used directly.namespace eval synth { # Unfortunately the name of the eCos executable is lost at this stage. # Within the eCos application it was held in argv[0], but that has been # overridden with the name of the auxiliary. However we have access to the # parent process id so we can use /proc to get the required information. variable ecos_appname "" catch { set synth::ecos_appname [file readlink "/proc/[set synth::_ppid]/exe"] set synth::ecos_appname [file tail $synth::ecos_appname] } # The install location can be determined from the script name. # This is used for e.g. loading bitmaps, even if ECOSYNTH_DEVEL # is set, because some of the files may be generated. # ECOSYNTH_DEVEL only affects Tcl scripts. variable install_dir [file join $synth::_ecosynth_libexecdir "ecos" $synth::_ecosynth_package_install] # Is the eCos application still running? This is worth keeping # track of so that send_reply and raise_interrupt do not try to # interact with a program that is no longer running. variable ecos_running 1 # This variable is used to enter the event loop variable _ecosynth_exit 0 # Is GUI mode enabled? variable flag_gui [expr { "" != [info commands "tk"] } ] # When running in GUI mode the GUI should stay up even after the application # has exited, so that the user can take a good look around. When running in # non-GUI mode this program should exit as soon it has finished cleaning up. variable flag_immediate_exit [expr { 0 == $synth::flag_gui} ] # Is the GUI ready to accept output? variable flag_gui_ready 0 # Flags and variables related to command-line arguments variable flag_help 0 variable flag_keep_going 0 variable flag_no_rc 0 variable flag_verbose 0 variable flag_debug 0 variable logfile "" variable target_definition "" variable geometry "<none>"}# }}}# {{{ Hooks & atexit support # ----------------------------------------------------------------------------# A lot of the flexibility of ecosynth is provided by hooks. Device scripts# and, more importantly, the per-user initrc and mainrc scripts can install# hooks that get called when an event occurs, for example when the eCos# applications attempts to transmit an ethernet packet.## A special hook is used to implement atexit handling. This involves redefining# the "exit" command so that it will invoke the appropriate hooks first.namespace eval synth { # All hooks are held in an array, indexed by the hook name, with each # array entry being a list of functions to be invoked. array set _hooks [list] proc hook_define { name } { if { [info exists synth::_hooks($name)] } { synth::report_error "Attempt to create hook $name which already exists.\n" } else { set synth::_hooks($name) [list] } } proc hook_defined { name } { return [info exists synth::_hooks($name)] } proc hook_add { name function } { if { ! [info exists synth::_hooks($name)] } { synth::report_error "Attempt to attach a function to an unknown hook $name\n" set synth::_hooks($name) [list] } lappend synth::_hooks($name) $function } proc hook_call { name args } { if { ! [info exists synth::_hooks($name) ] } { synth::report_error "Attempt to invoke unknown hook $name\n" } else { foreach function $synth::_hooks($name) { $function $args } } } # Define an initial set of hooks synth::hook_define "exit" ;# The auxiliary is exiting synth::hook_define "ecos_exit" ;# The eCos application has exited synth::hook_define "ecos_initialized" ;# eCos static constructors have run synth::hook_define "help" ;# --help}# Rename the builtin exit command so that it can still be accessed.rename exit _hook_real_exit# And define a replacement for exit which will invoke the appropriate# hook. Care has to be taken in case of recursive exit calls, each# hook function is only called once.proc exit { { code 0 } } { while { [llength $synth::_hooks(exit)] > 0 } { set handler [lindex $synth::_hooks(exit) end] set synth::_hooks(exit) [lrange $synth::_hooks(exit) 0 end-1] # For now assume no errors - it is not clear what could be done # about them anyway. catch { eval $handler [list]} } _hook_real_exit $code}# }}}# {{{ Output # ----------------------------------------------------------------------------# The usual set of utilities for issuing warnings, errors, ...#
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -