You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

The code for the CTK interface to the RTEMS shell is located in the rce/shell directory. All interaction with the RTEMS operating system is encapsulated away from the user inside the interface. Portions of the shell have been customized by the CTK group, and these customizations are listed below.

RTEMS Commands

The commands that the RTEMS 4.10.0 base shell provides are:

CTK defined commands

Shell Command Interface

Commands are added to the shell either at startup (CTK commands, above) or by the user with addCommand. All CTK and user defined commands are based on the Command class defined in rce/shell/Command.hh. The public interface to Command is:

namespace RCE {
namespace Shell {
  class Command {
  public:
    typedef int (*MainFunc)(int, char**);
  public:
    Command(std::string name, std::string topic, std::string alias = "");
    virtual ~Command();
    std::string name();
    std::string topic();
    std::string alias();
    virtual std::string usage() = 0;
    virtual MainFunc main() = 0;
    void initialize();
  };
}
}

The user defines their own command by implementing the pure virtual functions. A trivial example is below. This adds the command newCommand to the help namespace misc. The user provides a "MainFunc" type function (in this case NewCommand_main) and returns this function from NewCommand::main().

#include "rce/shell/Command.hh"
namespace FOO {
  using RCE::Shell::Command;
  class NewCommand : public Command {
  public:
    NewCommand();
    virtual ~NewCommand() {}
    virtual std::string usage();
    virtual MainFunc main();
  };

  int NewCommand_main(int argc, char** argv) {
    printf("This is a test of the new command\n");
    return 0;
  }

  NewCommand::NewCommand() : Command("newCommand", "misc") {}

  std::string NewCommand::usage() {
    static std::string u = "  newCommand     # Do nothing but print a message\n";
    return u;
  }

  Command::MainFunc NewCommand::main() {
    return NewCommand_main;
  }
}

The next step is to make this easily viewable from the dynamic linker. By default, the addCommand command will look for the entry point addCommands in the user's module and attempt to execute it. For the above example, the code looks like this:

extern "C" {
  void EXPORT addCommands(int unused) {
    // Example of dynamic adding a new command.
    // the user must first instantiate, then initialize
    NewCMD::NewCommand cmd; cmd.initialize();
  }
}

Users can use any arbitrary name for this entry point.

The last step is to compile it into a module and add it to the shell. The shell syntax for adding a command is:

addCommand [-e entryPoint] <path_to_module>

where the -e option is used when the entry point is not addCommands.

Note: When adding from multiple modules, each module's entry point must be distinct. Otherwise, the dynamic linker will complain about duplicate symbols, and the command won't be added correctly.

  • No labels