Implementing CLI commands

In document Openrg Programmer Guide 5.5 LATEST (Page 60-64)

Development Tutorial

Lines 6-7 Define that the API includes the files watchdog_mgt.h and

5.4.4 Implementing CLI commands

return (margin >= DEFAULT_MARGIN / 2 && margin <= DEFAULT_MARGIN);

}

The rg_conf and rg_conf_ram global variables are used to access the memory structures storing the configuration database. The set.h API allows reading and writing values to the configuration database. The configuration database stores only character strings, but provides an API to read and write these values as numbers, strings and boolean flags.

The static functions watchdog_set_get and watchdog_ram_set_get are used to retrieve the root of the Watchdog application configuration section in the database, for the persistent and volatile parts respectively.

The rest are API functions: watchdog_conf_get and watchdog_conf_set will retrieve and store the Watchdog configuration in the configuration database, including the margin and the boot message. watchdog_enable will turn on and off the keep-alive signal. watchdog_is_enabled is a boolean function used to check whether or not the Watchdog is sending keep-alive signals. Last is the validity check function, watchdog_is_margin_valid, which determines if the values of the margin are valid.

The API is now ready to be used by a client. In this case we are going to implement CLI commands to manage the Watchdog configuration.

5.4.4 Implementing CLI commands

The CLI commands that will manage and control the Watchdog application include the following commands, under the watchdog category:

conf Configure the Watchdog margin and end message.

start Hidden command to start the keep-alive signal.

status Show the current configuration of the Watchdog.

stop Hidden command to stop the keep-alive signal.

First, we need to define the CLI commands and register them with OpenRG's CLI command processor. We register the commands during the initialization of the mgt component using multilevel_cli_add_commands available from rg/pkg/cli/cli.h. The registration function requires that we fill two data structures. The first describes the category of the commands registered and the second defines the commands and their arguments.

rg/pkg/watchdog/mgt/commands.c

#include <main/mt_main.h>

#include <watchdog/mgt/watchdog_mgt.h>

static int watchdog_conf_cmd(estream_t *estream, int margin, char *boot_msg) {

}

static int watchdog_status_cmd(estream_t *estream) {

}

static int watchdog_start_cmd(estream_t *estream)

.desc = "Watchdog configuration and control", };

static cmd_item_t watchdog_commands[] = { {

.name = "conf",

.desc = "Configure the watchdog", .desc_long = "Usage:\r\n"

"\tconf <keep alive signal margin> <boot message>\r\n"

"\t<keep alive signal margin> - between 30 and 60 seconds\r\n", .function = watchdog_conf_cmd,

.param_types = { CMD_PARAM_ESTREAM, CMD_PARAM_INT, CMD_PARAM_STR, CMD_PARAM_END },

multilevel_cli_add_commands(&openrg_commands, &watchdog_cmd_category, watchdog_commands);

}

void watchdog_mgt_uninit(void) {

multilevel_cli_remove_commands(&openrg_commands, &watchdog_cmd_category, watchdog_commands);

}

The watchdog_cmd_category defines the command category that will be displayed when the help command is used with no arguments. The watchdog_commands array defines the commands that will be displayed when using the help command on the Watchdog category.

For each command we define the command name, a short and long description, the function that will handle the command, and the parameter types that are required by this command. You

may also specify that a command is hidden by setting the flags to CMD_ITEM_HIDDEN.

The parameter types allow both fixed and variable number of parameters. Indicating the pair CMD_PARAM_ARGC and CMD_PARAM_ARGV allows a variable number of arguments.

Otherwise the number of arguments is fixed.

The command processor performs basic validity checks on the parameter values including strings (CMD_PARAM_STR) and numbers (CMD_PARAM_INT). A special type defines an output stream (CMD_PARAM_ESTREAM) to which the function can write the output, using the estream_printf function. The parameter list must end with the value

CMD_PARAM_END.

The registration of commands should be hooked to the initialization of the Watchdog module.

We will have to call the mgt initialization function from the Watchdog initialization function.

This is done by creating an include file with the mgt initialization function, and using it in the Watchdog initialization function. Following is the mgt initialization API that must be written in:

rg/pkg/watchdog/mgt/watchdog_mgt_init.h

#ifndef _WATCHDOG_MGT_INIT_H_

#define _WATCHDOG_MGT_INIT_H_

/* Register and unregister the watchdog CLI commands */

void watchdog_mgt_init(void);

void watchdog_mgt_uninit(void);

#endif

Following are the lines that need to be added to the Watchdog initialization function in rg/pkg/

watchdog/watchdog_init.c:

rg_error(LCONSOLE, "Initializing Watchdog components.");

watchdog_mgt_init();

}

void watchdog_uninit(void) {

rg_error(LCONSOLE, "Un-initializing Watchdog components.");

watchdog_mgt_uninit();

}

Finally, all we need to do is implement the four CLI commands defined for the Watchdog, using the Watchdog mgt API, as follows:

rg/pkg/watchdog/mgt/commands.c

...

#include <watchdog/mgt/watchdog_mgt.h>

static int watchdog_conf_cmd(estream_t *estream, int margin, char *boot_msg) {

watchdog_conf_t conf;

if (!watchdog_is_margin_valid(margin)) {

estream_printf(estream, "Invalid margin");

return -1;

}

conf.margin = margin;

strncpyz(conf.boot_msg.msg, boot_msg, MAX_BOOT_MSG-1);

watchdog_conf_set(&conf);

openrg_reconf(FLASH_DELAYED_NOW);

return 0;

}

static int watchdog_status_cmd(estream_t *estream) {

watchdog_conf_t conf;

watchdog_conf_get(&conf);

estream_printf(estream, "Watchdog status: %s\r\n", watchdog_is_enabled() ? "Started" : "Stopped");

estream_printf(estream, "Keep alive signal margin: %d\r\n", conf.margin);

estream_printf(estream, "Boot message: %s\r\n", conf.boot_msg.msg);

return 0;

}

static int watchdog_start_cmd(estream_t *estream) {

watchdog_enable(1);

openrg_reconf(FLASH_DELAYED_NOW);

return 0;

}

static int watchdog_stop_cmd(estream_t *estream) {

watchdog_enable(0);

openrg_reconf(FLASH_DELAYED_NOW);

return 0;

}

At this point, we could configure and compile the entire tree, which takes a lot of time.

Instead, compilation of the package could be done incrementally. The 'make config' phase is responsible for exporting the headers. Since we have added a new component which requires exporting a header, we need to run 'make config' in the new mgt directory, and then run 'make':

$ cd rg/pkg/watchdog/mgt

$ make config

$ make

Once there are no errors in the mgt directory, we can go up to the Watchdog directory and run 'make', to link mgt with the rest of the Watchdog package.

$ cd ..

$ make

Now that the Watchdog package object is built, we can build the OpenRG main process by building rg/pkg/main.

$ cd ../main

$ make

The result should be in the rg/build/pkg/main/openrg program, which includes the Watchdog CLI commands. You can load it to the board and test the behavior of the commands. But before you do so, let's learn how to set up the default values for the persistent rg_conf entries.

In document Openrg Programmer Guide 5.5 LATEST (Page 60-64)

Related documents