Using Targets and Platforms

From RTSC-Pedia

Jump to: navigation, search
revision tip
—— LANDSCAPE orientation
[printable version]  [offline version]offline version generated on 24-Oct-2014 13:10 UTC

Using Targets and Platforms

Introduction to targets and platforms

Contents

Introduction

Before using target content produced by a third party, application developers must specify certain aspects of their development environment:

  1. the compiler and a runtime model supported by the compiler used to build the application, and
  2. the hardware platform used to run the application

In RTSC, a target "encapsulates" the compiler and runtime model information as a single named entity. Similarly, a platform is a named entity that encapsulates the hardware platform information. Informally, targets contain the information necessary to create a library that can be linked into an end-application and platforms contain all the information necessary to link and run an application on specific hardware.

Both targets and platforms are RTSC objects that are specified by the end-user via a string name. These names uniquely identify an appropriate object and allow tools that run at different times in the application's lifecycle (development, testing, and deployment) to access this object's attributes by simply using the object's name. For example, in Consuming Configurable Content, target and platform names are passed to the xdc.tools.configuro configuration tool to initialize the associated configuration Domain Object Model (DOM) prior to running an application's configuration script.

 
xs xdc.tools.configuro -t ti.targets.C64 -p ti.platforms.sim6xxx:TMS320C6416 app.cfg

This allows both the application's configuration script and any imported packages to conditionally select appropriate options, libraries, or prerequisite packages necessary to support the current configuration. Similarly, the RTSC Build Engine uses target names to initialize the build DOM prior to running package build scripts. Since both the target and platform names start with a name from the RTSC module or package namespace, target and platform specifications can be shared not just among local developers but also with developers in separate companies worldwide.

Application configuration scripts read but never modify target or platform attributes. It's important that targets and platforms remain unaltered since all models, including the build model and the runtime time model, rely on the fact that all models see the exactly the same target and platform information.

The need to specify compilers, runtime models, and hardware platforms is certainly not unique to RTSC or embedded software. For example, virtually all GNU Open Source packages include a configure shell script (created by the package producer via the Autoconf tool) that determines the compiler, runtime, and hardware platform from a combination of command line options to configure and the user's environment. Although this technique makes it very easy to rebuild and install GNU packages in workstation environments, it requires the end-user to have a fairly large set of UNIX-based tools including a "unixy" shell, it presumes that the packages are delivered in source form, and the information associated with the arguments to configure cannot be accessed after the package's installation except via ad hoc package-specific mechanisms.

Targets

Targets are implemented as any RTSC module that implements the xdc.bld.ITarget interface. While most users do not need to create new targets, the fact that they are represented as modules that implement a specific interface implies that

  1. anyone can add new targets without updating the XDCtools product
  2. target-specific extensions and detailed documentation is provided in the target module's *.xdc file
  3. tools can easily identify the entire set of available targets, and finally
  4. the information provided by all targets is formally specified by the xdc.bld.ITarget interface.

See Existing Targets for a list of targets and the compiler options that define these targets.

Target Names

Target names are simply the full name of the module that implements the ITarget interface. Since fully qualified module names (i.e., module names that include their package's name) are globally unique, this name can be used to uniquely identify a target. For example, the string "ti.targets.C64" uniquely identifies the module (ti.targets.C64) that contains all the information necessary to build a library of object files for a TMS320C64x processor running in little endian mode using TI's code generation tools.

Configuring Targets

Before a target can be used, it must be "configured". In particular, for each target you use, you must specify the installation directory of the toolchain that it encapsulates. Since targets are implemented as RTSC modules, the specification of the installation directory for a target is naturally expressed as a configuration parameter of the module. While this may seem odd at first, there are several advantages:

  • the same language used to configure target modules, XDCscript, is used to configure your build environment (one less language to learn);
  • this language, being a full programming language, makes it easy to integrate into existing build environments and support complex development environments with multiple versions of multiple toolchains;
  • since anyone can create new modules, anyone can create and publish new targets effectively extending XDCtools to support their favorite toolchain; and
  • each target can support a variety of compiler-specific configuration parameters to make use of the toolchain easier for the user.

Targets are always configured via a config.bld script and, for simple cases, this script quite straightforward; the only configuration parameter that you must set is the target's rootDir parameter.

config.bld
 
 
var C64P = xdc.useModule("ti.targets.C64P");  /* get the target module */
C64P.rootDir = "/user/local/ti/c64/6.1.2";    /* specify the target compiler's install directory */

For these simple cases, tools such as xdc.tools.configuro can implicitly create and use a config.bld based on command line parameters. However, unless you're happy to rely on the default compiler options and you use a single target, you'll find it easier to create and manage this file by hand. For more information about config.bld scripts, see Managing Compiler Toolchains.

Generic targets

Generic targets.  A target is usually created for a specific toolchain, where the names of commands and relative paths within in installation do not change. However, some targets are meant to represent a whole family of toolchains that generate compatible code but have different physical organization. The target modules in the package gnu.targets.arm are examples of such targets. A target from this package supports multiple Gnu Arm compilers, but the target is not preconfigured to use any of them by default. To use these targets, you must set the required parameter LONGNAME in a config.bld script, in addition to setting rootDir for the target.

For example, if version 2007q3 of the CodeSourcery GNU toolchain for Arm is installed in C:/CodeSourcery/arm-2007q3, the following settings in config.bld configure the gnu.targets.arm.GCArmv6 target to use that toolchain:

config.bld
 
 
 
var GCArmv6 = xdc.useModule("gnu.targets.arm.GCArmv6");
GCArmv6.rootDir = "C:/CodeSourcery/arm-2007q3"; 
GCArmv6.LONGNAME = "bin/arm-none-linux-gnueabi-gcc";

Target Runtime Support Packages

All targets name a package containing pre-built versions of the modules in the xdc.runtime package; see xdc.bld.ITarget.rts. This is done for several reasons:

  1. new targets can be added by anyone at any time without making any changes to the xdc.runtime package,
  2. all modules can assume the base set of services supplied by xdc.runtime without ever directly referring to any target-specific packages, and
  3. the end-user does not need to rebuild xdc.runtime modules when using a new target - she simply installs the target packages and associated runtime support packages like any other package.

However, there are two situations where the end-user must re-build the runtime support package identified by a target:

  1. when a new version of the xdc.runtime package is released, and
  2. if the version of the compiler used to produce the runtime support package is incompatible with the compiler version being used for the application; e.g., if the runtime support package was built using a newer version of the compiler than the end-user's compiler - compilers usually handle older object-file formats (because they are known) but new object file formats can easily break older compilers.

Runtime support packages are re-buildable by the end-user. You can either rebuild the package in-place or copy the package to a new repository that appears on your package path ahead of the original. For more information about how to rebuild a runtime support package see Re-building xdc.runtime Support Packages.

Platforms

Platforms are implemented as named instances from a RTSC module named "Platform" (contained in any package) that implements the xdc.platform.IPlatform interface. Packages containing a Platform module are called platform packages. While most users don't create new platform packages, the fact that platforms are instances of a module that implement a specific interface implies that

  • anyone can add new platforms without updating the XDCtools product
  • platform-specific extensions and detailed documentation is provided in the Platform module's *.xdc file
  • tools can identify the entire set of available platforms, and finally
  • the information provided by all platforms is formally specified by the xdc.platform.IPlatform interface.

Platforms are not implemented as modules because, unlike targets, there is little or no standardization among different end-applications. Virtually every embedded hardware platform is unique, where as it is common for each C6x platform to support one of a very small set of "standard" targets, for example.

Platform Names

Since platforms are implemented as instance objects rather than as a module, we can't simply use the RTSC module namespace to identify platforms. Unlike modules, which are pre-existing singleton objects with globally unique names, instance objects are generally anonymous objects created with parameters on an as needed basis. Platform instance names must uniquely identify both a module as well as the parameters used to create the instance.

Although end-users don't often create platform packages, they do need to define named platform instances. There are two ways to define named platform instances:

  1. add an entry to xdc.bld.BuildEnvironment.platformTable inside a config.bld script, or
  2. create a RTSC module with a configuration parameter of type xdc.platform.IPlatform.Instance.

In either case, both arguments of the xdc.platform.IPlatform.create() method are specified: a name string and a "structure" of platform-specific arguments.

Platform instance names reflect the two ways of defining named platform instances:

  1. "platform_pkg_name:instance_name_arg" refers to instances defined in config.bld, where platform_pkg_name is the name of the platform package containing the Platform module used to create the instance, instance_name_arg is the name argument, and the value of xdc.bld.BuildEnvironment.platformTable["platform_pkg_name:instance_name_arg"] is the platform-specific argument structure, and
  2. "module_name.config_param" refers to an instance specified by initializing a configuration parameter of type xdc.platform.IPlatform.Instance named config_param within the module named module_name. In this case, the name argument is "config_param" and the platform-specific argument structure is the initializer declared for this config parameter.

Defining Platform Instances via config.bld

Defining platform instances within config.bld is the easiest way to define new platform instances. But, while this method is sufficient for most situations, it is better to define platform instances as a configuration parameter of a RTSC module (described below).

To define a platform instance in config.bld, simply add a new entry to the xdc.bld.BuildEnvironment.platformTable map. For example, to add the platform instance named "ti.platforms.sim6xxx:C6416" that corresponds to an instance of the ti.platforms.sim6xxx.Platform module created with the deviceName parameter set to "TMS320C6416"

 
Build.platformTable["ti.platforms.sim6xxx:C6416"] = {deviceName: "TMS320C6416"};

You can define a "default" platform instance for a platform package by omitting the ":instance_name" suffix. In this case, the name of the platform instance is the same as the name of the platform package itself. While this is a convenient and concise way to name platform instances, it is important to not conflate platform instances with the package's used to create them.

 
 
 
Build.platformTable["ti.platforms.sim6xxx"] = {
    deviceName: "TMS320C6416", verbose: true
};

Defining Platform Instances via a RTSC Module Configuration Parameter

Although this technique of defining named platform instances requires the creation of a few simple files, it has several advantages: these platform instance definitions

  1. are available to any tool (not just the RTSC build and configuration tools)
  2. can be shared with external groups using the same techniques used to share any RTSC module
  3. will be automatically documented via the xdc.tools.cdoc tool (or any other documentation tool that reflects on RTSC IDL files).

Suppose you want to add a platform instance named "local.platforms.Sim6x.C6416" that corresponds to an instance of the ti.platforms.sim6xxx.Platform module created with the deviceName parameter set to "TMS320C6416". In this case, you must create a package named local.platforms with a module named Sim6x containing a configuration parameter named C6416 which is initialized with the deviceName parameter set to "TMS320C6416". While this is certainly a mouthful and enough to scare anyone away, it's really quite easy.

Simply create a directory named local/platforms in any repository in your package path with the following files and run the xdc command from this directory. This "compiles" the Sim6x module, making sure the deviceName parameter is a parameter of this platform, and makes the local.platforms.Sim6x module available to all scripts.

package.xdc
 
 
 
package local.platforms { 
    module Sim6x; 
}
package.bld
 
/* intentionally empty */
Sim6x.xdc
 
 
 
s1
 
 
 
import ti.platforms.sim6xxx.Platform;
metaonly module Sim6x {
    config Platform.Instance C6416 = 
        Platform.create("C6416", {
            deviceName: "TMS320C6416"
        });
}

There are times when you need to pass parameters that are "computed" based on the value of environment variables or the contents of certain files. Although you can't run script code inside a *.xdc file, you can initialize the configuration parameter using a script called from your package's initialization method. The following example illustrates how you can use the value from an environment variable to initialize a platform-specific parameter.

package.xdc
 
 
 
package local.platforms { 
    module Sim6x; 
}
package.bld
 
/* intentionally empty */
Sim6x.xdc
 
 
 
 
import ti.platforms.sim6xxx.Platform;
metaonly module Sim6x {
    config Platform.Instance C6416;
}

Since Sim6x.xdc no longer declares a static instance to be created. We must create the platform instance from within the Sim6x module's meta-domain implementation, Sim6x.xs.

Sim6x.xs
 
 
 
 
 
x1
 
 
 
 
var Platform = xdc.module("ti.platforms.sim6xxx.Platform");
 
function module$meta$init()
{
    /* initialize instances with params that are computed */
    this.C6416= Platform.create("C6416", {
        deviceName: "TMS320C6416",
        ftpath: java.lang.System.getenv("TOOLS") + "/ti/fts/1.05/"
     });
}

Notice that the syntax of the expression used to initialize the C6416 config parameter in the previous example's Sim64.xdc s1 is the same as that used to create an instance in the Sim64.xs file x1 .

Using the Generic Platform

While it is always possible to create a custom platform package for your hardware, it's not always necessary. The ti.platforms.generic platform package can be used to define platform instances for almost any hardware platform based on a TI device. The ti.platforms.generic.Platform module's instance create() method accepts parameters that specify the device, clock speed, and memory map for each instance. Thus, it's often possible to define a named platform instance using this platform package for your custom hardware without having to create a new platform package.

Suppose for example, that your application's platform uses a TMS320C6416 running at 600MHz with a block of external memory starting at 0x80000000 with 0x800000 bytes of memory for code or data. You can define an appropriate platform instance inside your config.bld script as follows:

config.bld (fragment)
 
 
 
 
 
 
 
 
 
 
 
 
 
Build.platformTable["ti.platforms.generic:C64"] = {
    deviceName: "TMS320C6416",
    catalogName: "ti.catalog.c6000",
    clockRate: 600,
    externalMemoryMap: [
        ["EXTMEM", {
            name: "EXTMEM",
            base: 0x80000000,
            len:  0x00800000,
            space: "code/data"}
        ],
    ]
};

Although the ti.platforms.generic platform can be used for a broad category of platforms, it's almost always better to use a platform package specifically created for your hardware (if one exists). Hardware specific platform packages

  • define the correct clock speed(s) and memory map for the device running your application;
  • enable all developers to create executables with consistent (and correct) definition of the hardware;
  • augment the device information with additional information that enables target-content packages to better select appropriate default settings; and
  • supply functions that allow you to more easily run executables built for the platform.

Use of the ti.platforms.generic platform generally means that there will be more configuration parameters that you'll have to explicitly specify (because platform information beyond the device can't be provided to contributing packages) and there is greater chance of using the wrong memory map, clock speed, etc.

Creating New Targets and Platforms

Although it is technically quite easy to define how to create a new target or platform package, as a practical matter, most developers either copy existing implementations or inherit from these implementations.

Alternately, you can use the RTSC Platform Wizard provided in CCSv4 as part of XDCtools to create platform packages. You can watch a demo that shows how to use this wizard.

The sections listed below provide concrete examples of both techniques as well are guidance to know which is best for your needs.

Creating Targets How to create a new target
Creating Platform Packages How to create a new platform package


Again, in many cases it is unnecessary to create a new target and platform. In fact, it's best to use an existing target or platform whenever possible.

Existing Targets Targets suppled with XDCtools
[printable version]  [offline version]offline version generated on 24-Oct-2014 13:10 UTC
Copyright © 2008 The Eclipse Foundation. All Rights Reserved
Personal tools
package reference