⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ecosynth.tcl

📁 开放源码实时操作系统源码.
💻 TCL
📖 第 1 页 / 共 5 页
字号:
# {{{  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 none
fconfigure $synth::_channel_from_app -encoding binary
fconfigure $synth::_channel_to_app   -encoding binary
fconfigure $synth::_channel_from_app -translation binary
fconfigure $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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -