Chapter 26. Manual Configuration

eCos developers will generally use the graphical Configuration Tool for configuring an eCos system and building the target library. However, some user prefer to use command line tools. These command line tools can also be used for batch operations on all platforms, for example as part of a nightly rebuild and testing procedure.

In the current release of the system the command line tools do not provide exactly the same functionality as the graphical tool. Most importantly, there is no facility to resolve configuration conflicts interactively.

The eCos configuration system, both graphical and command line tools, are under constant development and enhancement. Developers should note that the procedures described may change considerably in future releases.

26.1. Directory Tree Structure

When building eCos there are three main directory trees to consider: the source tree, the build tree, and the install tree.

The source tree, also known as the component repository, is read- only. It is possible to use a single component repository for any number of different configurations, and it is also possible to share a component repository between multiple users by putting it on a network drive.

The build tree contains everything that is specific to a particular configuration, including header and other files that contain configuration data, and the object files that result from compiling the system sources for this configuration.

The install tree is usually located in the install subdirectory of the build tree. Once an eCos system has been built, the install tree contains all the files needed for application development including the header files and the target library. By making copies of the install tree after a build it is possible to separate application development and system configuration, which may be desirable for some organizations.

26.2. Creating the Build Tree

Generating a build tree is a non-trivial operation and should not be attempted manually. Instead, eCos is shipped with a tool called ecosconfig that should be used to create a build tree.

Usually ecosconfig will be run inside the build tree itself. If you are creating a new build tree then typically you will create a new empty directory using the mkdir command, cd into that directory, and then invoke ecosconfig to create a configuration. Alternatively you can also use the --builddir option to specify the build directory if the build directory is to be stored in a location other than the current directory. By default, the configuration is stored in a file ecos.ecc in the current directory. The configuration may be modified by editing this file directly. ecosconfig itself deals with a number of coarse- grained configuration options such as the target platform and the packages that should be used.

The ecosconfig tool is also used subsequently to generate a build tree for a configuration. Once a build tree exists, it is possible to run ecosconfig again inside the same build tree. This will be necessary if your wish to change some of the configuration options.

ecosconfig does not generate the top-level directory of the build tree; you must do this yourself.

$ mkdir ecos-work
$ cd ecos-work

The next step is to run ecosconfig:

$ ecosconfig <qualifiers> <command>

26.2.1. ecosconfig qualifiers

The available command line qualifiers for ecosconfig are as follows. Multiple qualifiers may be used on the command line:

--help

Provides basic usage guidelines for the available commands and qualifiers.

--config=<file>

Specifies an eCos configuration save file for use by the tool. By default, the file ecos.ecc in the current directory is used. Developers may prefer to use a common location for all their eCos configurations rather than keep the configuration information in the base of the build tree.

--prefix=<dir>

Specifies an alternative location for the install tree. By default, the install tree resides inside the install directory in the build tree. Developers may prefer to locate the build tree in a temporary file hierarchy but keep the install tree in a more permanent location.

--srcdir=<dir>

Specifies the location of the component repository. By default, the tool uses the location specified in the ECOS_REPOSITORY environment variable. Developers may prefer to use of this qualifier if they are working with more than one repository.

--builddir=<dir>

Specifies an alternative location for the build directory. By default, the build directory will be created inside the current directory. Developers may prefer to locate the build tree in a temporary file hierarchy but keep the install tree in a more permanent location.

--no-resolve

Disables the implicit resolution of conflicts while manipulating the configuration data. developers may prefer to resolve conflicts by editing the eCos configuration save file manually.

--ignore-errors , -i

By default, ecosconfig will exit with an error code if the current configuration contains any conflicts, and it is not possible to generate or update a build tree for such configurations. This qualifier causes ecosconfig to ignore such problems, and hence it is possible to generate a build tree even if there are still conflicts. Of course, there are no guarantees that the resulting system will actually do anything.

--compat , -c

This option invokes the compatability mode of ecosconfig with the GUI configtool. It sets both the build and install directories of ecosconfig to the directories, relative to the configuration file, that would be created and used by the GUI configtool respectively. This option therefore cannot be used in conjuction with either the --prefix=<dir> or --builddir=<dir> options. This option is useful to application developers that regularly switch between using the CLI and GUI configuration tools.

--long , -l

Display long listing of packages, templates, targets and attributes.

--verbose , -v

Display more information.

--quiet , -q

Display less information.

The --config, --prefix and --srcdir qualifiers can also be written with two arguments, for example:

ecosconfig --srcdir <dir> ...

This simplifies filename completion with some shells.

26.2.2. ecosconfig commands

The available commands for ecosconfig are as follows:

list [<packages> | <templates> | <targets>]

Lists the available packages, targets and templates as installed in the eCos repository. The additional options <packages>, <templates> and <targets> restrict output to packages, templates and targets respectively and include the --long option support to provide additional information. Aliases and package versions are also reported.

new <target> [<template> [<version>]]

Creates a new eCos configuration for the specified target hardware and saves it. A software template may also be specified. By default, the template named ‘default’ is used. If the template version is not specified, the latest version is used.

target <target>

Changes the target hardware selection for the eCos configuration. This has the effect of unloading packages supporting the target selected previously and loading the packages which support the new hardware. This command will be used typically when switching between a simulator and real hardware.

[Note]Note

When switching targets between minor CPU variants, users are advised that inferred changes within common hardware packages are not reset or re-inferred unless a conflict arises as a result of the switch. For example, while a template may contain the SPI package, this package may be disabled in a configuration through inference as a result of the initial hardware lacking an SPI device. However, when switching to a processor variant with more cells (device support), such as one that includes an SPI device, the SPI package could remain disabled when the configuration is switched to the more superior variant unless it is marked as required within the CDL (i.e. it would conflict). Users are therefore advised that switching targets within a configuration may have unanticipated results and are recommended to use the process described in Section 15.2, “Switching Targets, Repositories and Versions”.

template <template> [<version>]

Changes the template selection for the eCos configuration. This has the effect of unloading packages specified by the template selected previously and loading the packages specified by the new template. By default, the latest version of the specified template is used.

add <packages>

Adds the specified packages to the eCos configuration. This command will be used typically when the template on which a configuration is based does not contain all the packages which are required.For example, add-on packages provided by third parties will not be known to the standard templates, so they will have to be added explicitly.

remove <packages>

Removes the specified packages from the eCos configuration. This command will be used typically when the template on which a configuration is based contains packages which are not required.

packages [loaded | active]

Provides package information regarding the eCos configuration rather than the eCos repository (as provided by the list command). The optional argument loaded (the default) will list what packages have been loaded into the eCos configuration while active will list active packages. The -- long option may also be included to provide additional information.

present <package> [<package> ...]

Tests for the presense of the packages and returns a status code of 0 if all the packages are present in the eCos configuration, or an error if not. This is useful for automated scripting of the creation of eCos configurations from the command line.

version <version> <packages>

Selects the specified version of a number of packages in the eCos configuration. By default, the most recent version of each package is used. This command will be used typically when an older version of a package is required.

check

Presents the following information concerning the current configuration:

  1. the selected target hardware

  2. the selected template

  3. additional packages

  4. removed packages

  5. the selected version of packages where this is not the most recent version

  6. conflicts in the current configuration

resolve

Resolves conflicts identified in the current eCos configuration by invoking an inference capability. Resolved conflicts are reported, but not all conflicts may be resolvable. This command will be used typically following manual editing of the configuration.

export <file>

Exports a minimal eCos configuration save file with the specified name. This file contains only those options which do not have their default value. Such files are used typically to transfer option values from one configuration to another.

import <file>

Imports a minimal eCos configuration save file with the specified name. The values of those options specified in the file are applied to the current configuration.

tree

Generates a build tree based on the current eCos configuration. This command will be used typically just before building eCos.Normally a build tree can only be generated if if the configuration has no unresolved conflicts, but --ignore-errors can be used to override this.

get_comment

User comments within eCos configurations are not preserved when modified with the configtool or ecosconfig. However, from eCosPro version 4.0 and above, the eCos Configuration file (normal prefix <.ecc>) the eCos Configuration file can contain user comments. The are located at the top of the Configuration file and can be fetched with this command. For example, both tools use User comments to store additional matedata information such as the name of the eCosPro profile used to generate the configuration. If no profile information is provided to either the configtool or ecosconfig, both tools will use this comment to set a default profile for the configuration of the profile is valid.

add_comment <comment>

Append the comment <comment> to the user comments within the eCos configuration file.

set_comment <comment>

Replaces the user comments within the eCos configuration file with <comment>. This will erase any profile indicators stored within the configuration file when the eCos configuration was created.

26.3. Conflicts and constraints

Configuration options are not completely independent. For example the C library's strtod() and atof() functions rely on the math library package to provide certain functionality. If the math library package is removed then the C library can no longer provide these functions. Each package describes constraints like these in CDL "requires" properties. If a constraint is not satisfied, then the configuration contains a conflict. For any given conflict there can be several resolution options. For example, it would be possible to add the math library package back to the configuration, or to disable the strtod() and atof() functions.

The eCos configuration tools will report any conflicts in the current configuration. If there are any such conflicts then the configuration is usually unsafe and it makes no sense to build and run eCos in such circumstances. In fact, any attempt at building eCos is likely to fail. In exceptional cases it is possible to override this by using e.g. the --ignore-errors qualifier with ecosconfig.

Many constraints are fairly simple in nature, and the configuration tools contain an inference engine which can resolve the associated conflicts automatically. For example, if the math library package is removed then the inference engine can resolve the resulting conflict by disabling the configuration option for strtod() and atof(). All such changes will be reported. Sometimes the inference engine cannot resolve a conflict, for example it is not allowed to override a change that has been made explicitly by the user. Sometimes it will find a solution which does not match the application's requirements.

A typical session involving conflicts would look something like this:

$ ecosconfig new pid

This creates a new configuration with the default template. For most targets this will not result in any conflicts, because the default settings for the various options meet the requirements of the default template.

For some targets there may be conflicts and the inference engine would come into play.

$ ecosconfig remove libm
U CYGSEM_LIBC_STDIO_SCANF_FLOATING_POINT, new inferred value 0
U CYGFUN_LIBC_strtod, new inferred value 0
U CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT, new inferred value 0

ecosconfig reports that this change caused three conflicts, all in the C library. The inference engine was able to resolve all the conflicts and update the relevant configuration options accordingly.

To suppress the inference engine --no-resolve can be used:

$ ecosconfig new pid
$ ecosconfig --no-resolve remove libm
C CYGSEM_LIBC_STDIO_SCANF_FLOATING_POINT, "requires" constraint not satisfied:  CYGPKG_LIBM
C CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT, "requires" constraint not satisfied: CYGPKG_LIBM
C CYGFUN_LIBC_strtod, "requires" constraint not satisfied: CYGPKG_LIBM

Three unresolved conflicts are reported.

The check command can be used to get the current state of the configuration, and the --verbose qualifier will provide additional information:

$ ecosconfig --srcdir /home/bartv/ecc/ecc --verbose check
Target: pid
Template: default
Removed:
  CYGPKG_LIBM
3 conflict(s):
  C CYGFUN_LIBC_strtod, "requires" constraint not satisfied: CYGPKG_LIBM
Possible solution:
  CYGFUN_LIBC_strtod -> 0
  CYGSEM_LIBC_STDIO_SCANF_FLOATING_POINT -> 0
  C CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT, "requires" constraint not satisfied: CYGPKG_LIBM
Possible solution:
  CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT -> 0
  C CYGSEM_LIBC_STDIO_SCANF_FLOATING_POINT, "requires" constraint not satisfied:  CYGPKG_LIBM
Possible solution:
  CYGSEM_LIBC_STDIO_SCANF_FLOATING_POINT -> 0

If the proposed solutions are acceptable, the resolve command can be used to apply them:

$ ecosconfig resolve
U CYGSEM_LIBC_STDIO_SCANF_FLOATING_POINT, new inferred value 0
U CYGFUN_LIBC_strtod, new inferred value 0
U CYGSEM_LIBC_STDIO_PRINTF_FLOATING_POINT, new inferred value 0

The current configuration is again conflict-free and it is possible to generate a build tree. The --quiet qualifier can be used to suppress the change messages, if desired.

When changing individual configuration options by editing the ecos.ecc file (as described below), the resulting system should be checked and any problems should be resolved. For example, if CYGFUN_LIBC_strtod is explicitly enabled in the savefile:

$ edit ecos.ecc
$ ecosconfig check
Target: pid
Template: default
Removed:
CYGPKG_LIBM
1 conflict(s):
C CYGFUN_LIBC_strtod, "requires" constraint not satisfied: CYGPKG_LIBM
$ ecosconfig resolve
C CYGFUN_LIBC_strtod, "requires" constraint not satisfied: CYGPKG_LIBM

In this case the inference engine cannot resolve the conflict automatically because that would involve changing a user setting. Any attempt to generate a build tree will fail:

$ ecosconfig --srcdir /home/bartv/ecc/ecc tree
C CYGFUN_LIBC_strtod, "requires" constraint not satisfied: CYGPKG_LIBM
Unable to generate build tree, this configuration still contains conflicts.
Either resolve the conflicts or use --ignore-errors

It is still possible to generate a build tree:

$ ecosconfig --srcdir /home/bartv/ecc/ecc --ignore-errors tree
C CYGFUN_LIBC_strtod, "requires" constraint not satisfied: CYGPKG_LIBM
$ make

In this case eCos will fail to build. In other cases of unresolved conflicts eCos may build, but may not run. In general all conflicts should be resolved by editing the ecos.ecc file, by letting the inference engine make appropriate changes, or by other means, before any attempt is made to build or run eCos.

26.4. Building the System

Once a build tree has been generated with ecosconfig, building eCos is straightforward:

$ make

The build tree contains the subdirectories, makefiles, and everything else that is needed to generate the default configuration for the selected architecture and platform. The only requirement is that the tools needed for that architecture, for example powerpc-eabi- g++, are available using the standard search path. If this is not the case then the make will fail with an error message. If you have a multiprocessor system then it may be more efficient to use:

$ make -j n

where n is equal to the number of processors on your system.

Once the make process has completed, the install tree will contain the header files and the target library that are needed for application development.

It is also possible to build the system’s test cases for the current configuration:

$ make tests

The resulting test executables will end up in a tests subdirectory of the install tree.

If disk space is scarce then it is possible to make the copy of the install tree for application development purposes, and then use:

$ make clean

The build tree will now use up a minimum of disk space — the bulk of what is left consists of configuration header files that you may have edited and hence should not be deleted automatically. However, it is possible to rebuild the system at any time without re-invoking ecosconfig, just by running make again.

Under exceptional circumstances it may be necessary to run make clean for other reasons, such as when a new release of the toolchain is installed. The toolchain includes a number of header files which are closely tied to the compiler, for example limits.h, and these header files are not and should not be duplicated by eCos. The makefiles perform header file dependency analysis, so that when a header file is changed all affected sources will be rebuilt during the next make. This is very useful when the configuration header files are changed, but it also means that a build tree containing information about the locations of header files must be rebuilt. If a new version of the toolchain is installed and the old version is removed then this location information is no longer accurate, and make will complain that certain dependencies cannot be satisfied. Under such circumstances it is necessary to do a make clean first.

26.5. Packages

eCos is a component architecture. The system comes as a number of packages which can be enabled or disabled as required, and new packages can be added as they become available. Unfortunately, the packages are not completely independent: for example the µITRON compatibility package relies almost entirely on functionality provided by the kernel package, and it would not make sense to try to build µITRON if the kernel was disabled. The C library has fewer dependencies: some parts of the C library rely on kernel functionality, but it is possible to disable these parts and thus build a system that has the C library but no kernel. The ecosconfig tool has the capability of checking that all the dependencies are satisfied, but it may still be possible to produce configurations that will not build or (conceivably) that will build but not run. Developers should be aware of this and take appropriate care.

By default, ecosconfig will include all packages that are appropriate for the specified hardware in the configuration. The common HAL package and the eCos infrastructure must be present in every configuration. In addition, it is always necessary to have one architectural HAL package and one platform HAL package. Other packages are optional, and can be added or removed from a configuration as required.

The application may not require all of the packages; for example, it might not need the µITRON compatibility package, or the floating point support provided by the math library. There is a slight overhead when eCos is built because the packages will get compiled, and there is also a small disk space penalty. However, any unused facilities will get stripped out at link- time, so having redundant packages will not affect the final executable.

26.6. Coarse-grained Configuration

Coarse-grained configuration of an eCos system means making configuration changes using the ecosconfig tool. These changes include:

  1. switching to different target hardware

  2. switching to a different template

  3. adding or removing a package

  4. changing the version of a package

Whenever ecosconfig generates or updates an eCos configuration, it generates a configuration save file.

Suppose that the configuration was first created using the following command line:

$ ecosconfig new stdeval1

To change the target hardware to the Cogent CMA28x PowerPC board, the following command would be needed:

$ ecosconfig target cma28x

To switch to the PowerPC simulator instead:

$ ecosconfig target psim

As the hardware changes, hardware-related packages such as the HAL packages and device drivers will be added to and removed from the configuration as appropriate.

[Note]Note

See the note on unintended consequences in Section 15.2, “Switching Targets, Repositories and Versions”.

To remove any package from the current configuration, use the remove command:

$ ecosconfig remove uitron

You can disable multiple packages using multiple arguments, for example:

$ ecosconfig remove uitron libm

If this turns out to have been a mistake then you can re-enable one or more packages with the add command:

$ ecosconfig add libm

Changing the desired version for a package is also straightforward:

$ ecosconfig version v4_0_1 kernel

It is necessary to regenerate the build tree and header files following any changes to the configuration before rebuilding eCos:

$ ecosconfig tree

26.7. Fine-grained Configuration

ecosconfig only provides coarse-grained control over the configuration: the hardware, the template and the packages that should be built. Unlike the Configuration Tool, ecosconfig does not provide any facilities for manipulating finer-grained configuration options such as how many priority levels the scheduler should support. There are hundreds of these options, and manipulating them by means of command line arguments would not be sensible.

In the current system fine-grained configuration options may be manipulated by manual editing of the configuration file. When a file has been edited in this way, the ecosconfig tool should be used to check the configuration for any conflicts which may have been introduced:

$ ecosconfig check

The check command will list all conflicts and will also rewrite the configuration file, propagating any changes which affect other options. The user may choose to resolve the conflicts either by re-editing the configuration file manually or by invoking the inference engine using the resolve command:

$ ecosconfig resolve

The resolve command will list all conflicts which can be resolved and save the resulting changes to the configuration.

It is necessary to regenerate the build tree and header files following any changes to the configuration before rebuilding eCos:

$ ecosconfig tree

All the configuration options and their descriptions are listed in the eCos Reference Manual.

26.8. Editing an eCos Savefile

The eCos configuration information is held in a single savefile, typically ecos.ecc, which can be generated by either the GUI configuration tool or by the command line ecosconfig tool. The file normally exists at the top level of the build tree. It is a text file, allowing the various configurations options to be edited inside a suitable text editor or by other programs or scripts, as well as in the GUI config tool.

An eCos savefile is actually a script in the Tcl programming language, so any modifications to the file need to preserve Tcl syntax. For most configuration options, any modifications will be trivial and there is no need to worry about Tcl syntax. For example, changing a 1 to a 0 to disable an option. For more complicated options, for exampleCYGDAT_UITRON_TASK_EXTERNS, which involves some lines of C code, more care has to be taken. If an edited savefile is no longer a valid Tcl script then the configuration tools will be unable to read back the data for further processing, for example to generate a build tree. An outline of Tcl syntax is given below. One point worth noting here is that a line that begins with a “#” is usually a comment, and the bulk of an eCos savefile actually consists of such comments, to make it easier to edit.

26.8.1. Header

An eCos savefile begins with a header, which typically looks something like this:

# eCos saved configuration
# ---- commands --------------------------------------------------------
# This section contains information about the savefile format.
# It should not be edited. Any modifications made to this section
# may make it impossible for the configuration tools to read
# the savefile.
cdl_savefile_version 1;
cdl_savefile_command cdl_savefile_version {};
cdl_savefile_command cdl_savefile_command {};
cdl_savefile_command
cdl_configuration { description hardware template package };
cdl_savefile_command cdl_package { value_source user_value wizard_value inferred_value };
cdl_savefile_command cdl_component { value_source user_value wizard_value inferred_value };
cdl_savefile_command cdl_option { value_source user_value wizard_value inferred_value };
cdl_savefile_command cdl_interface { value_source user_value wizard_value inferred_value };

This section of the savefile is intended for use by the configuration system, and should not be edited. If this section is edited then the various configuration tools may no longer be able to read in the modified savefile.

26.8.2. Toplevel Section

The header is followed by a section that defines the configuration as a whole. A typical example would be:

# ---- toplevel --------------------------------------------------------
# This section defines the toplevel configuration object. The only
# values that can be changed are the name of the configuration and
# the description field. It is not possible to modify the target,
# the template or the set of packages simply by editing the lines
# below because these changes have wide-ranging effects. Instead
# the appropriate tools should be used to make such modifications.
cdl_configuration eCos {
  description ““ ;
  # These fields should not be modified.
  hardware    pid ;
  template    uitron ;
  package -hardware CYGPKG_HAL_ARM current ;
  package -hardware CYGPKG_HAL_ARM_PID current ;
  package -hardware CYGPKG_IO_SERIAL current ;
  package -template CYGPKG_HAL current ;
  package -template CYGPKG_IO current ;
  package -template CYGPKG_INFRA current ;
  package -template CYGPKG_KERNEL current ;
  package -template CYGPKG_UITRON current ;
  package -template CYGPKG_LIBC current ;
  package -template CYGPKG_LIBM current ;
  package -template CYGPKG_DEVICES_WALLCLOCK current ;
  package -template CYGPKG_ERROR current ;
};

This section allows the configuration tools to reload the various packages that make up the configuration. Most of the information should not be edited. If it is necessary to add a new package or to remove an existing one then the appropriate tools should be used for this, for example:

$ ecosconfig remove CYGPKG_LIBM

There are two fields which can be edited. Configurations have a name; in this case eCos. They can also have a description, which is some arbitrary text. The configuration tools do not make use of these fields, they exist so that users can store additional information about a configuration.

26.8.3. Conflicts Section

The toplevel section is followed by details of all the conflicts (if any) in the configuration, for example:

# ---- conflicts -------------------------------------------------------
# There are 2 conflicts.
#
# option CYGNUM_LIBC_TIME_DST_DEFAULT_OFFSET
#   Property LegalValues
#   Illegal current value 100000
#   Legal values are: -90000 to 90000
#
# option CYGSEM_LIBC_TIME_CLOCK_WORKING
#   Property Requires
#   Requires constraint not satisfied: CYGFUN_KERNEL_THREADS_TIMER

When editing a configuration you may end up with something that is invalid. Any problems in the configuration will be reported in the conflicts section. In this case there are two conflicts. The option CYGNUM_LIBC_TIME_DST_DEFAULT_OFFSET has been given an illegal value: typically this would be fixed by searching for the definition of that option later on in the savefile and modifying the value. The second conflict is more interesting, an unsatisfied requires constraint. Configuration options are not independent: disabling some functionality in, say, the kernel, can have an impact elsewhere; in this case the C library. The various dependencies between the options are specified by the component developers and checked by the configuration system. In this case there are two obvious ways in which the conflict could be resolved: re- enabling CYGFUN_KERNEL_THREADS_TIMER, or disabling CYGSEM_LIBC_TIME_CLOCK_WORKING. Both of these options will be listed later on in the file.

Some care has to be taken when modifying configuration options, to avoid introducing new conflict. For instance it is possible that there might be other options in the system which have a dependency on CYGSEM_LIBC_TIME_CLOCK_WORKING, so disabling that option may not be the best way to resolve the conflict. Details of all such dependencies are provided in the appropriate places in the savefile.

It is not absolutely required that a configuration be conflict- free before generating a build tree and building eCos. It is up to the developers of each component to decide what would happen if an attempt is made to build eCos while there are still conflicts. In serious cases there is likely to be a compile-time failure, or possibly a link-time failure. In less serious cases the system may build happily and the application can be linked with the resulting library, but the component may not quite function as intended - although it may still be good enough for the specific needs of the application. It is also possible that everything builds and links, but once in a while the system will unaccountably crash. Using a configuration that still has conflicts is done entirely at the user’s risk.

26.8.4. Data Section

The bulk of the savefile lists the various packages, components, and options, including their values and the various dependencies. A number of global options come first, especially those related to the build process such as compiler flags. These are followed by the various packages, and the components and options within those packages, in order.

Packages, components and options are organized in a hierarchy. If a particular component is disabled then all options and sub-components below it will be inactive: any changes made to these will have no effect. The savefile contains information about the hierarchy in the form of comments, for example:

cdl_package CYGPKG_KERNEL ...
# >
cdl_component CYGPKG_KERNEL_EXCEPTIONS ...
# >
cdl_option CYGSEM_KERNEL_EXCEPTIONS_DECODE ...
cdl_option CYGSEM_KERNEL_EXCEPTIONS_GLOBAL ...
# <
cdl_component CYGPKG_KERNEL_SCHED ...
# >
cdl_option CYGSEM_KERNEL_SCHED_MLQUEUE ...
cdl_option CYGSEM_KERNEL_SCHED_BITMAP ...
# <
# <

This corresponds to the following hierarchy:

CYGPKG_KERNEL
  CYGPKG_KERNEL_EXCEPTIONS
    CYGSEM_KERNEL_EXCEPTIONS_DECODE
    CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
  CYGPKG_KERNEL_SCHED
    CYGSEM_KERNEL_SCHED_MLQUEUE
    CYGSEM_KERNEL_SCHED_BITMAP

Providing the hierarchy information in this way allows programs or scripts to analyze the savefile and readily determine the hierarchy. It could also be used by a sufficiently powerful editor to support structured editing of eCos savefiles. The information is not used by the configuration tools themselves since they obtain the hierarchy from the original CDL scripts.

Each configurable entity is preceded by a comment, of the following form:

# Kernel schedulers
# doc: ref/ecos-ref/ecos-kernel-overview.html#THE-SCHEDULER
# The eCos kernel provides a choice of schedulers. In addition
# there are a number of configuration options to control the
# detailed behaviour of these schedulers.
cdl_component CYGPKG_KERNEL_SCHED {
  ...
};

This provides a short textual alias Kernel schedulers for the component. If online documentation is available for the configurable entity then this will come next. Finally there is a short description of the entity as a whole. All this information is provided by the component developers.

Each configurable entity takes the form:

<type> <name> {
  <data>
};

Configurable entities may not be active. This can be either because the parent is disabled or inactive, or because there are one or more active_if properties. Modifying the value of an inactive entity has no effect on the configuration, so this information is provided first:

cdl_option CYGSEM_KERNEL_EXCEPTIONS_DECODE {
  # This option is not active
  # The parent CYGPKG_KERNEL_EXCEPTIONS is disabled
  ...
};
...
cdl_option CYGIMP_IDLE_THREAD_YIELD {
  # This option is not active
  # ActiveIf constraint: (CYGNUM_KERNEL_SCHED_PRIORITIES == 1)
  #     CYGNUM_KERNEL_SCHED_PRIORITIES == 32
  #   --> 0
  ...
};

For CYGIMP_IDLE_THREAD_YIELD the savefile lists the expression that must be satisfied if the option is to be active, followed by the current value of all entities that are referenced in the expression, and finally the result of evaluating that expression.

Not all options are directly modifiable in the savefile. First, the value of packages (which is the version of that package loaded into the configuration) cannot be modified here.

cdl_package CYGPKG_KERNEL {
  # Packages cannot be added or removed, nor can their version be changed,
  # simply by editing their value. Instead the appropriate configuration
  # should be used to perform these actions.
  ...
};

The version of a package can be changed using e.g.:

$ ecosconfig version 1.3 CYGPKG_KERNEL

Even though a package’s value cannot be modified here, it is still important for the savefile to contain the details. In particular packages may impose constraints on other configurable entities and may be referenced by other configurable entities. Also it would be difficult to understand or extract the configuration’s hierarchy if the packages were not listed in the appropriate places in the savefile.

Some components (or, conceivably, options) do not have any associated data. Typically they serve only to introduce another level in the hierarchy, which can be useful in the context of the GUI configuration tool.

cdl_component CYGPKG_HAL_COMMON_INTERRUPTS {
  # There is no associated value.
};

Other components or options have a calculated value. These are not user-modifiable, but typically the value will depend on other options which can be modified. Such calculated options can be useful when controlling what gets built or what ends up in the generated configuration header files. A calculated value may also effect other parts of the configuration, for instance, via a requires constraint.

cdl_option BUFSIZ {
  # Calculated value: CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO ? CYGNUM_LIBC_STDIO_BUFSIZE : 0
  #     CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO == 1
  #     CYGNUM_LIBC_STDIO_BUFSIZE == 256
  # Current_value: 256
};

A special type of calculated value is the interface. The value of an interface is the number of active and enabled options which implement that interface. Again the value of an interface cannot be modified directly; only by modifying the options which implement the interface. However, an interface can be referenced by other parts of the configuration.

cdl_interface CYGINT_KERNEL_SCHEDULER {
  # Implemented by CYGSEM_KERNEL_SCHED_MLQUEUE, active, enabled
  # Implemented by CYGSEM_KERNEL_SCHED_BITMAP, active, disabled
  # This value cannot be modified here.
  # Current_value: 1
  # Requires: 1 == CYGINT_KERNEL_SCHEDULER
  #     CYGINT_KERNEL_SCHEDULER == 1
  #   --> 1
  # The following properties are affected by this value
  # interface CYGINT_KERNEL_SCHEDULER
  #     Requires: 1 == CYGINT_KERNEL_SCHEDULER
}; 

If the configurable entity is modifiable then there will be lines like the following:

cdl_option CYGSEM_KERNEL_SCHED_MLQUEUE {
  ...
  # Flavor: bool
  # No user value, uncomment the following line to provide one.
  # user_value 1
  # value_source default
  # Default value: 1
  ...
};

Configurable entities can have one of four different flavors: none, bool, data and booldata. Flavor none indicates that there is no data associated with the entity, typically it just acts as a placeholder in the overall hierarchy. Flavor bool is the most common, it is a simple yes-or-no choice. Flavor data is for more complicated configuration choices, for instance the size of an array or the name of a device. Flavor booldata is a combination of bool and data: the option can be enabled or disabled, and there is some additional data associated with the option as well.

In the above example the user has not modified this particular option, as indicated by the comment and by the commented-out user_value line. To disable this option the file should be edited to:

cdl_option CYGSEM_KERNEL_SCHED_MLQUEUE {
  ...
  # Flavor: bool
  # No user value, uncomment the following line to provide one.
  user_value 0
  # value_source default
  # Default value: 1
  ...
}

The comment preceding the user_value 0 line can be removed if desired, otherwise it will be removed automatically the next time the file is read and updated by the configuration tools.

Much the same process should be used for options with the data flavor, for example:

cdl_option CYGNUM_LIBC_TIME_DST_DEFAULT_OFFSET {
  # Flavor: data
  # No user value, uncomment the following line to provide one.
  # user_value 3600
  # value_source default
  # Default value: 3600
  # Legal values: -90000 to 90000
};

can be changed to:

cdl_option CYGNUM_LIBC_TIME_DST_DEFAULT_OFFSET {
  # Flavor: data
  user_value 7200
  # value_source default
  # Default value: 3600
  # Legal values: -90000 to 90000
};

Note that the original text provides the default value in the user_value comment, on the assumption that the desired new value is likely to be similar to the default value. The value_source comment does not need to be updated, it will be fixed up if the savefile is fed back into the configuration system and regenerated.

For options with the booldata flavor, the user_value line needs take two arguments. The first argument is for the boolean part, the second for the data part. For example:

cdl_component CYGNUM_LIBM_COMPATIBILITY {
  # Flavor: booldata
  # No user value, uncomment the following line to provide one.
  # user_value 1 POSIX
  # value_source default
  # Default value: 1 POSIX
  # Legal values:  “POSIX” “IEEE” “XOPEN” “SVID”
  ...
};

could be changed to:

cdl_component CYGNUM_LIBM_COMPATIBILITY {
  # Flavor: booldata
  user_value 1 IEEE
  # value_source default
  # Default value: 1 POSIX
  # Legal values:  “POSIX” “IEEE” “XOPEN” “SVID”
  ...
};

or alternatively, if the whole component should be disabled, to:

cdl_component CYGNUM_LIBM_COMPATIBILITY {
  # Flavor: booldata
  user_value 0 POSIX
  # value_source default
  # Default value: 1 POSIX
  # Legal values:  “POSIX” “IEEE” “XOPEN” “SVID”
  ...
};

Some options take values that span multiple lines. An example would be:

cdl_option CYGDAT_UITRON_MEMPOOLVAR_INITIALIZERS {
  # Flavor: data
  # No user value, uncomment the following line to provide one.
  # user_value \
  # “CYG_UIT_MEMPOOLVAR( vpool1, 2000 ), \\
  #  CYG_UIT_MEMPOOLVAR( vpool2, 2000 ), \\
  #  CYG_UIT_MEMPOOLVAR( vpool3, 2000 ),”
  # value_source default
  # Default value: \
  #     “CYG_UIT_MEMPOOLVAR( vpool1, 2000 ), \\
  #      CYG_UIT_MEMPOOLVAR( vpool2, 2000 ), \\
  #      CYG_UIT_MEMPOOLVAR( vpool3, 2000 ),”
};

Setting a user value for this option involves uncommenting and modifying all relevant lines, for example:

cdl_option CYGDAT_UITRON_MEMPOOLVAR_INITIALIZERS {
  # Flavor: data
  user_value \
  “CYG_UIT_MEMPOOLVAR( vpool1, 4000 ), \\
  CYG_UIT_MEMPOOLVAR( vpool2, 4000 ),”
  # value_source default
  # Default value: \
  #     “CYG_UIT_MEMPOOLVAR( vpool1, 2000 ), \\
  #      CYG_UIT_MEMPOOLVAR( vpool2, 2000 ), \\
  #      CYG_UIT_MEMPOOLVAR( vpool3, 2000 ),”
};

In such cases appropriate care has to be taken to preserve Tcl syntax, as discussed below.

The configuration system has the ability to keep track of several different values for any given option. All options start off with a default value, in other words their value source is set to default. If a configuration involves conflicts and the configuration system’s inference engine is allowed to resolve these automatically then it may provide an inferred value instead, for example:

cdl_option CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT {
  # Flavor: bool
  # No user value, uncomment the following line to provide one.
  # user_value 1
  # The inferred value should not be edited directly.
  inferred_value 0
  # value_source inferred
  # Default value: 1
  ...
};

Inferred values are calculated by the configuration system and should not be edited by the user. If the inferred value is not correct then a user value should be substituted instead:

cdl_option CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT {
  # Flavor: bool
  user_value 1
  # The inferred value should not be edited directly.
  inferred_value 0
  # value_source inferred
  # Default value: 1
  ...
}; 

The inference engine will not override a user value with an inferred one. Making a change like this may well re-introduce a conflict, since the inferred value was only calculated to resolve a conflict. Another run of the inference engine may find a different and more acceptable way of resolving the conflict, but this is not guaranteed and it may be up to the user to examine the various dependencies and work out an acceptable solution.

Inferred values are listed in the savefile because the exact inferred value may depend on the order in which changes were made and conflicts were resolved. If the inferred values were absent then it is possible that reloading a savefile would not exactly restore the configuration. Default values on the other hand are entirely deterministic so there is no actual need for the values to be listed in the savefile. However, the default value can be very useful information so it is provided in a comment.

Occasionally the user will want to do some experimentation, and temporarily switch an option from a user value back to a default or inferred one to see what the effect would be. This could be achieved by simply commenting out the user value. For instance, if the current savefile contains:

cdl_option CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT {
  # Flavor: bool
  user_value 1
  # The inferred value should not be edited directly.
  inferred_value 0
  # value_source user
  # Default value: 1
  ...
};

then the inferred value could be restored by commenting out or removing the user_value line:

cdl_option CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT {
  # Flavor: bool
  # user_value 1
  # The inferred value should not be edited directly.
  inferred_value 0
  # value_source user
  # Default value: 1
  ...
};

This is fine for simple values. However if the value is complicated then there is a problem: commenting out the user_value line or lines means that the user value becomes invisible to the configuration system, so if the savefile is loaded and then regenerated the information will be lost. An alternative approach is to keep the user_value but explicitly set the value_source line, for example:

cdl_option CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT {
  # Flavor: bool
  user_value 1
  # The inferred value should not be edited directly.
  inferred_value 0
  value_source inferred
  # Default value: 1
  ...
};

In this case the configuration system will use the inferred value for the purposes of dependency analysis etc., even though a user value is present. To restore the user value the value_source line can be commented out again. If there is no explicit value_source then the configuration system will just use the highest priority one: the user value if it exists; otherwise the inferred value if it exists; otherwise the default value which always exists.

The default value for an option can be a simple constant, or it can be an expression involving other options. In the latter case the expression will be listed, together with the values for all options referenced in the expression and the current result of evaluating that expression. This is for informational purposes only, the default value is always recalculated deterministically when loading in a savefile.

cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX {
  # Flavor: data
  # No user value, uncomment the following line to provide one.
  # user_value arm-elf
  # value_source default
  # Default value:  CYGHWR_THUMB ? “thumb-elf” : “arm-elf”
  #     CYGHWR_THUMB == 0
  #   --> arm-elf
};

For options with the data or booldata flavor, there are likely to be constraints on the possible values. If the value is supposed to be a number in a given range and a user value of “hello world” is provided instead then there are likely to be compile-time failures. Component developers can specify constraints on the legal values, and these will be listed in the savefile.

cdl_option X_TLOSS {
  # Flavor: data
  # No user value, uncomment the following line to provide one.
  # user_value 1.41484755040569E+16
  # value_source default
  # Default value: 1.41484755040569E+16
  # Legal values: 1 to 1e308
};
cdl_component CYGNUM_LIBM_COMPATIBILITY {
  # Flavor: booldata
  # No user value, uncomment the following line to provide one.
  # user_value 1 POSIX
  # value_source default
  # Default value: 1 POSIX
  # Legal values:  “POSIX” “IEEE” “XOPEN” “SVID”
  ...
};

In some cases the legal values list may be an expression involving other options. If so then the current values of the referenced options will be listed, together with the result of evaluating the list expression, just as for default value expressions.

If an illegal value is provided then this will result in a conflict, listed in the conflicts section of the savefile. For more complicated options a simple legal values list is not sufficient to allow the current value to be validated, and the configuration system will be unable to flag conflicts. This issue will be addressed in future releases of the configuration system.

Following the value-related fields for a given option, any requires constraints belonging to this option will be listed. These constraints are only effective if the option is active and, for bool and booldata flavors, enabled. If some aspect of eCos functionality is inactive or disabled then it cannot impose any constraints on the rest of the system. As usual, the full expression will be listed followed by the current values of all options that are referenced and the result of evaluating the expression:

cdl_option CYGSEM_LIBC_TIME_TIME_WORKING {
  ...
  # Requires: CYGPKG_DEVICES_WALLCLOCK
  #     CYGPKG_DEVICES_WALLCLOCK == current
  #   --> 1
};

When modifying the value of an option it is useful to know not only what constraints the option imposes on the rest of the system but also what other options in the system depend in some way on this one. The savefile provides this information:

cdl_option CYGFUN_KERNEL_THREADS_TIMER {
  ...
  # The following properties are affected by this value
  # option CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT
  #     Requires: CYGFUN_KERNEL_THREADS_TIMER
  # option CYGIMP_UITRON_STRICT_CONFORMANCE
  #     Requires: CYGFUN_KERNEL_THREADS_TIMER
  # option CYGSEM_LIBC_TIME_CLOCK_WORKING
  #     Requires: CYGFUN_KERNEL_THREADS_TIMER
};

26.8.5. Tcl Syntax

eCos savefiles are implemented as Tcl scripts, and are read in by running the data through a standard Tcl interpreter that has been extended with a small number of additional commands such as cdl_option and cdl_configuration. In many cases this is an implementation detail that can be safely ignored while editing a savefile: simply replacing a 1 with a 0 to disable some functionality is not going to affect whether or not the savefile is still a valid Tcl script and can be processed by a Tcl interpreter. However, there are more complicated cases where an understanding of Tcl syntax is at least desirable, for example:

cdl_option CYGDAT_UITRON_MEMPOOLVAR_EXTERNS {
  # Flavor: data
  user_value \
  “static char vpool1\[ 2000 \], \\
  vpool2\[ 2000 \], \\
  vpool3\[ 2000 \];”
  # value_source default
  # Default value: \
  #     “static char vpool1\[ 2000 \], \\
  #      vpool2\[ 2000 \], \\
  #      vpool3\[ 2000 \];”
};

The backslash at the end of the user_value line is processed by the Tcl interpreter as a line continuation character. The quote marks around the user data are also interpreted by the Tcl interpreter and serve to turn the entire data field into a single argument. The backslashes preceding the opening and closing square brackets prevent the Tcl interpreter from treating these characters specially, otherwise there would be an attempt at command substitution as described below. The double backslashes at the end of each line of the data will be turned into a single backslash by the Tcl interpreter, rather than escaping the newline character, so that the actual data seen by the configuration system is:

static char vpool1[ 2000 ], \
vpool2[ 2000 ], \
vpool3[ 2000 ];

This is of course the data that should end up in the µITRON configuration header file. The opening and closing braces surrounding the entire body of the option data are also significant and cause this body to be passed as a single argument to the cdl_option command. The closing semicolon is optional in this example, but provides a small amount of additional robustness if the savefile is edited such that it is no longer a valid Tcl script. If the data contained any $ characters then these would have to be treated specially as well, via a backslash escape.

In spite of what all the above might seem to suggest, Tcl is actually a very simple yet powerful scripting language: the syntax is defined by just eleven rules. On occasion this simplicity means that Tcl’s behaviour is subtly different from other languages, which can confuse newcomers.

When the Tcl interpreter is passed some data such as puts Hello, it splits this data into a command and its arguments. The command will be terminated by a newline or by a semicolon, unless one of the quoting mechanisms is used. The command and each of its arguments are separated by white space. So in the following example:

puts Hello
set x 42 

will result in two separate commands being executed. The first command is puts and is passed a single argument, Hello. The second command is set and is passed two arguments, x and 42. The intervening newline character serves to terminate the first command, and a semi-colon separator could be used instead:

puts Hello;set x 42

Any white space surrounding the semicolon is just ignored because it does not serve to separate arguments.

Now consider the following:

set x Hello world

This is not valid Tcl. It is an attempt to invoke the set command with three arguments: x, Hello, and world. The set only takes two arguments, a variable name and a value, so it is necessary to combine the data into a single argument by quoting:

set x “Hello world”

When the Tcl interpreter encounters the first quote character it treats all subsequent data up to but not including the closing quote as part of the current argument. The quote marks are removed by the interpreter, so the second argument passed to the set command is just Hello world without the quote characters. This can be significant in the context of eCos savefiles. For instance, consider the following configuration option:

cdl_option CYGDAT_LIBC_STDIO_DEFAULT_CONSOLE {
  # Flavor: data
  # No user value, uncomment the following line to provide one.
  # user_value “\”/dev/ttydiag\””
  # value_source default
  # Default value: “\”/dev/ttydiag\””
};

The desired value of the configuration option should be a valid C string, complete with quote characters. If the savefile was edited to:

cdl_option CYGDAT_LIBC_STDIO_DEFAULT_CONSOLE {
  # Flavor: data
  user_value “/dev/ttydiag”
  # value_source default
  # Default value: “\”/dev/ttydiag\””
};

then the Tcl interpreter would remove the quote marks when the savefile is read back in, so the option’s value would not have any quote marks and would not be a valid C string. The configuration system is not yet able to perform the required validation so the following #define would be generated in the configuration header file:

#define CYGDAT_LIBC_STDIO_DEFAULT_CONSOLE /dev/ttydiag 

This is likely to cause a compile-time failure when building eCos.

A quoted argument continues until the closing quote character is encountered, which means that it can span multiple lines. This can also be encountered in eCos savefiles, for instance, in the CYGDAT_UITRON_MEMPOOLVAR_EXTERNS example mentioned earlier. Newline or semicolon characters do not terminate the current command in such cases.

The Tcl interpreter supports much the same forms of backslash substitution as other common programming languages. Some backslash sequences such as \n will be replaced by the appropriate character. The sequence \\ will be replaced by a single backslash. A backslash at the very end of a line will cause that backslash, the newline character, and any white space at the start of the next line to be replaced by a single space. Hence the following two Tcl commands are equivalent:

puts  “Hello\nworld\n”
puts \
  “Hello
  world
“

In addition to quote and backslash characters, the Tcl interpreter treats square brackets, the $ character, and braces specially. Square brackets are used for command substitution, for example:

puts “The answer is [expr 6 * 9]”

When the Tcl interpreter encounters the square brackets it will treat the contents as another command that should be executed first, and the result of executing that is used when continuing to process the script. In this case the Tcl interpreter will execute the command expr 6 * 9, yielding a result of 54, and then the Tcl interpreter will execute puts “The answer is 54”. It should be noted that the interpreter contains only one level of substitution: if the result of performing command substitution performs further special characters such as square brackets then these will not be treated specially.

Command line substitution is very unlikely to prove useful in the context of an eCos savefile, but it is part of the Tcl language and hence cannot be easily suppressed while reading in a savefile. As a result care has to be taken when savefile data involves square brackets. Consider the following:

cdl_option CYGDAT_UITRON_MEMPOOLFIXED_EXTERNS {
  ...
  user_value \
  “static char fpool1[ 2000 ],
  fpool2[ 2000 ];”
  ...
};

The Tcl interpreter will interpret the square brackets as an attempt at command substitution and hence it will attempt to execute the command 2000 with no arguments. No such command is defined by the Tcl language or by the savefile-related extensions provided by the configuration system, so this will result in an error when an attempt is made to read back the savefile. Instead it is necessary to backslash-escape the square brackets and thus suppress command substitution:

cdl_option CYGDAT_UITRON_MEMPOOLFIXED_EXTERNS {
  ...
  user_value \
  “static char fpool1\[ 2000 \],
  fpool2\[ 2000 \];”
  ...
}; 

Similarly the $ character is used in Tcl scripts to perform variable substitution:

set x [expr 6 * 9]
    puts “The answer is $x” 

Variable substitution, like command substitution, is very unlikely to prove useful in the context of an eCos savefile. Should it be necessary to have a $ character in configuration data then again a backslash escape needs to be used.

cdl_option FOODAT_MONITOR_PROMPT {
  ...
  user_value “\$ “
  ...
};

Braces are used to collect a sequence of characters into a single argument, just like quotes. The difference is that variable, command and backslash substitution do not occur inside braces (with the sole exception of backslash substitution at the end of a line). So, for example, the CYGDAT_UITRON_MEMPOOL_EXTERNFIXED_EXTERNS value could be written as:

cdl_option CYGDAT_UITRON_MEMPOOLFIXED_EXTERNS {
  ...
  user_value \
  {static char fpool1[ 2000 ],
  fpool2[ 2000 ];}
  ...
};

The configuration system does not use this when generating savefiles because for simple edits of a savefile by inexperienced users the use of brace characters is likely to be a little bit more confusing than the use of quotes.

At this stage it is worth noting that the basic format of each configuration option in the savefile makes use of braces:

cdl_option <name> {
  ...
};

The configuration system extends the Tcl language with a small number of additional commands such as cdl_option. These commands take two arguments, a name and a body, where the body consists of all the text between the braces. First a check is made that the specified option is actually present in the configuration. Then the body is executed in a recursive invocation of the Tcl interpreter, this time with additional commands such as user_value and value_source. If, after editing, the braces are not correctly matched up then the savefile will no longer be a valid Tcl script and errors will be reported when the savefile is loaded again.

Comments in Tcl scripts are introduced by a hash character #. However, a hash character only introduces a comment if it occurs where a command is expected. Consider the following:

# This is a comment
puts “Hello” # world 

The first line is a valid comment, since the hash character occurs right at the start where a command name is expected. The second line does not contain a comment. Instead it is an attempt to invoke the puts command with three arguments: Hello, # and world. These are not valid arguments for the puts command so an error will be raised.

If the second line was rewritten as:

puts “Hello”; # world

then this is a valid Tcl script. The semicolon identifies the end of the current command, so the hash character occurs at a point where the next command would start and hence it is interpreted as the start of a comment.

This handling of comments can lead to subtle behaviour. Consider the following:

cdl_option WHATEVER {
  # This is a comment }
  user_value 42
  ...
}

Consider the way the Tcl interpreter processes this. The command name and the first argument do not pose any special difficulties. The opening brace is interpreted as the start of the next argument, which continues until a closing brace is encountered. In this case the closing brace occurs on the second line, so the second argument passed to cdl_option is \n # This is a comment . This second argument is processed in a recursive invocation of the Tcl interpreter and does not contain any commands, just a comment. Toplevel savefile processing then resumes, and the next command that is encountered is user_value. Since the relevant savefile code is not currently processing a configuration option this is an error. Later on the Tcl interpreter would encounter a closing brace by itself, which is also an error. Fortunately this sequence of events is very unlikely to occur when editing generated savefiles.

This should be sufficient information about Tcl to allow for safe editing of eCos savefiles. Further information is available from a wide variety of sources, for example the book Tcl and the Tk Toolkit by John K Ousterhout.

26.9. Editing the Sources

For many users, controlling the packages and manipulating the available configuration options will be sufficient to create an embedded operating system that meets the application's requirements. However, since eCos is shipped entirely in source form, it is possible to go further when necessary: you can edit the eCos sources themselves. This requires some understanding of the way the eCos build system works.

The most obvious place to edit the source code is directly in the component repository. For example, you could edit the file kernel/<version>/src/sync/mutex.cxx to change the way kernel mutexes work, or possibly just to add some extra diagnostics or assertions. Once the file has been edited, it is possible to invoke make at the top level of the build tree and the target library will be rebuilt as required. A small optimization is possible: the build tree is largely a mirror of the component repository, so it too will contain a subdirectory kernel/<version> ; if make is invoked in this directory then it will only check for changes to the kernel sources, which is a bit more efficient than checking for changes throughout the component repository.

Editing a file in the component repository is fine if this tree is used for only one eCos configuration. If the repository is used for several different configurations, however, and especially if it is shared by multiple users, then making what may be experimental changes to the master sources would be a bad idea. The build system provides an alternative. It is possible to make a copy of the file in the build tree, in other words copy mutex.cxx from the kernel/<version>/src/sync directory in the component repository to kernel/<version>/src/sync in the build tree, and edit the file in the build tree. When make is invoked it will pick up local copies of any of the sources in preference to the master versions in the component repository. Once you have finished modifying the eCos sources you can install the final version back in the component repository. If the changes were temporary in nature and only served to aid the debugging process, then you can discard the modified version of the sources.

The situation is slightly more complicated for the header files that a package may export, such as the C library’s stdio.h header file, which can be found in the directory language/c/libc/<version>/include. If such a header file is changed, either directly in the component repository or after copying it to the build tree, then make must be invoked at the top level of the build tree. In cases like this it is not safe to rebuild just the C library because other packages may depend on the contents of stdio.h.

26.10. Modifying the Memory Layout

Each eCos platform package is supplied with linker script fragments which describe the location of memory regions on the evaluation board and the location of memory sections within these regions. The correct linker script fragment is selected and included in the eCos linker script target.ld when eCos is built.

It is not necessary to modify the default memory layouts in order to start development with eCos. However, it will be necessary to edit a linker script fragment when the memory map of the evaluation board is changed. For example, if additional memory is added, the linker must be notified that the new memory is available for use. As a minimum, this would involve modifying the length of the corresponding memory region. Where the available memory is non-contiguous, it may be necessary to declare a new memory region and reassign certain linker output sections to the new region.

Linker script fragments and memory layout header files should be edited within the eCos install tree. They are located at include/pkgconf/mlt_*.*. Where multiple start-up types are in use, it will be necessary to edit multiple linker script fragments and header files. The information provided in the header file and the corresponding linker script fragment must always match. A typical linker script fragment is shown below:

Example 26.1.  eCos linker script fragment

MEMORY
{
  rom : ORIGIN = 0x40000000, LENGTH = 0x80000
  ram : ORIGIN = 0x48000000, LENGTH = 0x200000
}
SECTIONS
{
  SECTIONS_BEGIN
  SECTION_rom_vectors (rom, 0x40000000, LMA_EQ_VMA)
  SECTION_text (rom, ALIGN (0x1), LMA_EQ_VMA)
  SECTION_fini (rom, ALIGN (0x1), LMA_EQ_VMA)
  SECTION_rodata (rom, ALIGN (0x1), LMA_EQ_VMA)
  SECTION_rodata1 (rom, ALIGN (0x1), LMA_EQ_VMA)
  SECTION_fixup (rom, ALIGN (0x1), LMA_EQ_VMA)
  SECTION_gcc_except_table (rom, ALIGN (0x1), LMA_EQ_VMA)
  SECTION_data (ram, 0x48000000, FOLLOWING (.gcc_except_table))
  SECTION_bss (ram, ALIGN (0x4), LMA_EQ_VMA)
  SECTIONS_END
}

The file consists of two blocks, the MEMORY block contains lines describing the address (ORIGIN) and the size (LENGTH) of each memory region. The MEMORY block is followed by the SECTIONS block which contains lines describing each of the linker output sections. Each section is represented by a macro call. The arguments of these macros are ordered as follows:

  1. The memory region in which the section will finally reside.

  2. The final address ( VMA ) of the section. This is expressed using one of the following forms:

    n

    at the absolute address specified by the unsigned integer n

    ALIGN (n)

    following the final location of the previous section with alignment to the next n-byte boundary

  3. The initial address (LMA) of the section. This is expressed using one of the following forms:

    LMA_EQ_VMA

    the LMA equals the VMA (no relocation)

    AT (n)

    at the absolute address specified by the unsigned integer n

    FOLLOWING (.name)

    following the initial location of section name

In order to maintain compatibility with linker script fragments and header files exported by the eCos Configuration Tool, the use of other expressions within these files is not recommended.

Note that the names of the linker output sections will vary between target architectures. A description of these sections can be found in the specific GCC documentation for your architecture.