Implementing a Command
FreeRTOS+CLI is an extensible framework that allows the application writer
to define and register their own command line input commands. This page describes how to
write a function that implements the behaviour of a command.
Function inputs and outputs
Functions that implement the behaviour of a user defined command must have the following
interface (prototype):
portBASE_TYPE xFunctionName( int8_t *pcWriteBuffer,
size_t xWriteBufferLen,
const int8_t *pcCommandString );
Following is a description of the
parameters that will be passed into the function when it is
called, and the value that must be returned.
Parameters:
|
pcWriteBuffer
|
This is the buffer into which any generated output
should be written. For example, if the function
is simply going to return th fixed string "Hello World",
then the string is written into pcWriteBuffer. Output
must always be null terminated.
|
|
xWriteBufferLen
|
This is the size of the buffer pointed to by the
pcWriteBuffer parameter. Writing more than xWriteBufferLen
characters into pcWriteBuffer will cause a buffer
overflow.
|
|
pcCommandString
|
A pointer to the entire command
string. Having access to the entire command string
allows the function implementation to extract the
command parameters - if there are any. FreeRTOS+CLI provides
helper functions
that accept the command string and
return the command parameters - so explicit string
parsing is not required. Examples are provided on
this page.
|
Returns:
Executing some commands will result in more than a single line of output being
produced. For example,
a file system "dir" (or "ls") command will generate a line of output for each
file in a directory. If there are three files in the
directory, the output might look as below:
file1.txt
file2.txt
file3.txt
To minimise RAM usage, and ensure RAM usage is deterministic, FreeRTOS+CLI
allows functions that implement command behaviour to output a single
line at a time. The function return value is used to indicate whether
the output line is the end of the output, or if there are more lines
to be generated.
Return pdFALSE if the generated output is the end of the output, meaning
there are no more lines to be generated, and the command execution
is complete.
Return pdTRUE if the returned output is not the end of the output, and
there are still one or more lines to be generated before the command
execution is complete.
To continue the example of the "dir" command that outputs three file
names:
-
The first time the function that implements the dir command is called,
it is possible to only output the first line (file1.txt). If this is done
the function must return pdTRUE to indicate there are more lines to follow.
-
The second time the function that implements the dir command is called,
it is possible to only output the second line (file2.txt). If this is done
the function must return pdTRUE again to indicate there are more lines to follow.
-
The third time the function that implements the dir command is called,
only the third line (file3.txt) will be output. This time, there are
no more lines to output, so the function must return pdFALSE.
Alternatively, if there is sufficient RAM, and the value passed in
xWriteBufferLen is large enough, all three lines could have been
returned at once - in which case the function must return pdFALSE on
its first execution.
Each time a command is executed, FreeRTOS+CLI will repeatedly call
the function that implements the command behaviour, until the function
returns pdFALSE.
Examples
The following examples are provided below:
-
A command that takes no parameters and returns a single string.
-
A command that takes no parameters and returns multiple strings,
one line at a time.
-
A command that expects a fixed number of parameters.
-
A command that accepts a variable number of parameters, and
returns a variable number of strings one line at a time.
Example 1: A command with no parameters
The FreeRTOS vTaskList() API function generates a table containing
information on the state of each task. The table contains a line of text
for each task. The command implemented in Example 1 outputs this table.
Example 1 demonstrates the simple case where the entire table is output at once. The comments
in the code provide more explanation.
static portBASE_TYPE prvTaskStatsCommand( int8_t *pcWriteBuffer,
size_t xWriteBufferLen,
const int8_t *pcCommandString )
{
( void ) xWriteBufferLen;
vTaskList( pcWriteBuffer + strlen( pcHeader ) );
return pdFALSE;
}
Example 1: Outputting multiple lines at once
|
Example 2: Returning multiple lines one line at a time
Every command registered with FreeRTOS+CLI has its own help string. The
help string is one line of text that demonstrates how the command is used.
FreeRTOS+CLI includes a "help" command that returns all the help strings,
providing the user with a list of available commands along with instructions
on how each command is used. Example 2 shows the implementation of the
help commend. Unlike example 1, where all the output was generated in one
go, example 2 generates a single line at a time. Note this function is
not re-entrant.
static portBASE_TYPE prvHelpCommand( int8_t *pcWriteBuffer,
size_t xWriteBufferLen,
const int8_t *pcCommandString )
{
static const xCommandLineInputListItem *pxCommand = NULL;
signed portBASE_TYPE xReturn;
if( pxCommand == NULL )
{
pxCommand = &xRegisteredCommands;
}
strncpy( pcWriteBuffer,
pxCommand->pxCommandLineDefinition->pcHelpString,
xWriteBufferLen );
pxCommand = pxCommand->pxNext;
if( pxCommand == NULL )
{
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
return xReturn;
}
Example 2: Generating multiple lines of output, one line at a time
|
Example 3: A command with a fixed number of parameters
Some commands take parameters. For example, a file system "copy"
command needs the name of the source file and the name of the destination
file. Example 3 is a framework for a copy command and is provided
to demonstrate how command parameters are accessed and used.
Note that, if this command is declared to take two parameters when
it is registered, FreeRTOS+CLI will not even call the command unless
exactly two parameters are supplied.
static portBASE_TYPE prvCopyCommand( int8_t *pcWriteBuffer,
size_t xWriteBufferLen,
const int8_t *pcCommandString )
{
int8_t *pcParameter1, *pcParameter2;
portBASE_TYPE xParameter1StringLength, xParameter2StringLength, xResult;
pcParameter1 = FreeRTOS_CLIGetParameter
(
pcCommandString,
1,
&xParameter1StringLength
);
pcParameter2 = FreeRTOS_CLIGetParameter( pcCommandString,
2,
&xParameter2StringLength );
pcParameter1[ xParameter1StringLength ] = 0x00;
pcParameter2[ xParameter2StringLength ] = 0x00;
xResult = prvCopyFile( pcParameter1, pcParameter2 );
if( xResult == pdPASS )
{
*pcWriteBuffer == NULL;
}
else
{
snprintf( pcWriteBuffer, xWriteBufferLen, "Error during copy\r\n\r\n" );
}
return pdFALSE;
}
Example 3: Accessing and using the command parameters
|
Example 4: A command with a variable number of parameters
Example 4 demonstrates how to create and implement a command that
accepts a variable number of parameters. FreeRTOS+CLI will
not check the number of supplied parameters, and the
implementation of the command simply echos parameter back,
one at a time. For example, if the assigned command string was
"echo_parameters", if the user enters:
"echo_parameters one two three four"
Then the generated out will be:
The parameters were:
1: one
2: two
3: three
4: four
static portBASE_TYPE prvParameterEchoCommand( int8_t *pcWriteBuffer,
size_t xWriteBufferLen, c
onst int8_t *pcCommandString )
{
int8_t *pcParameter;
portBASE_TYPE lParameterStringLength, xReturn;
static portBASE_TYPE lParameterNumber = 0;
if( lParameterNumber == 0 )
{
sprintf( pcWriteBuffer, "The parameters were:\r\n" );
lParameterNumber = 1L;
xReturn = pdPASS;
}
else
{
pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter
(
pcCommandString,
lParameterNumber,
&lParameterStringLength
);
if( pcParameter != NULL )
{
memset( pcWriteBuffer, 0x00, xWriteBufferLen );
sprintf( pcWriteBuffer, "%d: ", lParameterNumber );
strncat( pcWriteBuffer, pcParameter, lParameterStringLength );
strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) );
xReturn = pdTRUE;
lParameterNumber++;
}
else
{
pcWriteBuffer[ 0 ] = 0x00;
xReturn = pdFALSE;
lParameterNumber = 0;
}
}
return xReturn;
}
Example 3: Accessing a variable number of parameters
|
|
|