Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Before going into an example of µC/Shell usage, a few design concepts have to be explained.  Since µC/HTTPs Shell is compliant with the all available browser for computer system. It was written for target systems running µC/OS-II or µC/OS-III, and µC/TCP-IP. This section describes the µC/HTTPs usage.

Table of Contents

Interface with FS

The sample application that comes with µC/HTTPs assumes the presence of µC/FS, as mentioned in See Directories and Files. It is possible to port µC/HTTPs so it is used with other file system by providing an appropriate implementation of apps_fs.c and apps_fs.h . Example template files to port the file system are available in the uC-HTTPs\FS\Template directory.

µC/HTTPs is distributed with file system ports for µC/FS, and the port corresponding to the version used by your project should be moved into the µC/FS directory structure. Furthermore, the source files of that port must only be included in your project from the µC/FS module. This is necessary since multiple applications might share the same file system port, and including it from several locations would cause linker and/or build errors.

Alternatively, if you do not want to move it to your file system directory structure, you may include it directly from µC/HTTPs. If you do so, make sure other applications relying on the file system port do not include it too.

Using µC/HTTPs with the Static File System

µC/HTTPs could be used without a conventional file system in order to test its functionalities.

The static file system relies on C arrays to represent the various files, and those files are accessible only for reading. µC/HTTPs ships with a very basic web page consisting of an html and a gif file. If you wish to include your own files in this file system, you will have to follow a few simple steps.

First of all, you will have to download a small utility called “bin2c.com ” from Micrium’s web site to help you create a C array from any given file. You need to create these arrays for every single file you want to include in this file system. Type “bin2c.com /? ” at the command prompt for more information on its usage.

The C array having been generated by this utility then have to be included into your project’s application (see file static_files.h for complete example). Finally, prior to being able to access the files on the static file system, you need to initialize it and add the files to it, just like it is being done in See ..

Also note that additional configuration values have to be added to your app_cfg.h file. Refer to See µC/HTTPs Configuration. for more information).

Transferring Files to Use with µC/HTTPs

Transferring files on the file system for use with the µC/HTTPs module is outside the scope of this document. For this purpose, you could use a FTP server or client, such as µC/FTPs or µC/FTPc, or again use a mass storage media to into your file system.

Make sure the files intended to be served by the µC/HTTPs module are located below HTTPs_CFG_FS_ROOT , or the web server will not be able to transfer them to web browsers.

µC/HTTPs Configuration

The µC/HTTPs not associated with any particular product, modules in need of a shell facility (such as µC/TELNETs) interact with it by means of an application callback function.  This way, those modules are able to use or not to use the shell in a totally transparent manner.

From the caller point of view, once the commands have been developed and the initialization performed, all that is needed to do is a call the main µC/Shell execution function:


Code Block
languagecpp
CPU_INT16S  Shell_Exec (CPU_CHAR         *in,
                        SHELL_OUT_FNCT    out_fnct,
                        SHELL_CMD_PARAM  *pcmd_param,
                        SHELL_ERR        *perr);


This function parses the ‘ in ’ parameter, a NUL terminated string containing a complete command line (command name, followed by possible arguments being separated by spaces), just like this one:


Code Block
languagecpp
App_Test -a -b -c readme.txt


Once parsed, that is once the command name and its arguments have been extracted, µC/Shell looks into its command tables for a command match (in this case App_Test is the name of the command), and invokes it.

Note that the Shell_Exec() function also has a ‘out_fnct’ argument, which is a pointer to a callback that handles the details of responding to the requester.  In other words, if called by µC/TELNETs, then µC/TELNETs has to provide the details of the response;  if called by a UART, the UART should handle the response.  Finally, the ‘pcmd_param’ is a pointer to a structure containing additional parameters for the command to use.

For more details on this function, please proceed with the next section.

Commands, Callbacks, and Data Types

µC/Shell commands (i.e., commands placed in a ‘command table’) all have this prototype:


Code Block
languagecpp
 CPU_INT16S  My_Cmd (CPU_INT16U        argc,
                    CPU_CHAR         *argv[],
                    SHELL_OUT_FNCT    out_fnct,
                    SHELL_CMD_PARAM  *pcmd_param);


where ‘ argc ’ is a count of the arguments supplied and ‘ argv ’, an array of pointers to the strings which are those arguments.  As for the return value, it is command specific, and will be used as the return value for the Shell_Exec() function.  However, in case of an error, SHELL_EXEC_ERR should be returned. 

Commands are also defined by the SHELL_CMD_FNCT data type:


Code Block
languagecpp
typedef  CPU_INT16S  (*SHELL_CMD_FNCT)(CPU_INT16U        ,
                                       CPU_CHAR        **,
                                       SHELL_OUT_FNCT    ,
                                       SHELL_CMD_PARAM  *);


As mentioned in the preceding section, each command is responsible for responding to its requester, and this is done with the help of the last parameter: the pointer to the output function.  This function has the following prototype:


Code Block
languagecpp
CPU_INT16S  My_Out_Fnct (CPU_CHAR    *pbuf,
                         CPU_INT16U   buf_len,
                         void        *popt);


where ‘pbuf’ is a pointer to a response buffer having a length of ‘buf_len’.  The third parameter, ‘popt’, is an optional argument used to provide implementation specific information (port number, UART identification, etc.).  As for the return value, it is suggested to return the number of data octets transmitted, SHELL_OUT_RTN_CODE_CONN_CLOSED if the link has been closed, and SHELL_OUT_ERR for any other error.

The output function is also defined by a data type, SHELL_OUT_FNCT:


Code Block
languagecpp
typedef  CPU_INT16S  (*SHELL_OUT_FNCT)(CPU_CHAR    *,
                                       CPU_INT16U   ,
                                       void        * );


Finally the ‘ pcmd_param ’ is used to pass additional information to the command.  The current implementation has provision for the current working directory, as well as an option parameter used by the output function:


Code Block
languagecpp
typedef  struct  shell_cmd_param {
    void         *pcur_working_dir;
    void         *pout_opt;
    CPU_BOOLEAN  *psession_active;
} SHELL_CMD_PARAM;


Note that future implementation could add members to this structure to support more parameters.

µC/Shell Startup Code

We provide you with an example (i.e the application code) use of µC/Shell which is found in app.c  and it was written to provide a startup example on how to use the capabilities of the µC/Shell module.  app.c simply initializes µC/OS?II, µC/TCP-IP and µC/Shell, and creates a few tasks and other kernel objects that will give the user information about the state of the system.  Note that you DO NOT need an RTOS like µC/OS?II or a TCP/IP stack like µC/TCP-IP to use µC/Shell.

Before you can use µC/Shell, the following has to be performed:

  1. Develop/create your command(s)
  2. Implement output functions (if needed)
  3. Initialize µC/Shell

This section of the manual will give you some examples of the above steps.  Note that some sections of the source code have been removed or modified to help focus on the µC/Shell module use.

Anchor
Listing - Output function
Listing - Output function

Code Block
languagecpp
titleListing - Output function
linenumberstrue
CPU_INT16S  App_TestShellOut (CPU_CHAR   *pbuf,                                (1)
                              CPU_INT16U  buf_len,
                              void       *popt)
{
    APP_TRACE_DEBUG((pbuf));                                                   (2)
    APP_TRACE_DEBUG((" executed.\n\r"));
 
    return (buf_len);                                                          (3)
}


Panel
bgColor#f0f0f0

(1) Function implementing the ‘output’ facility. This function MUST have the prototype specified in section 2.01.

(2) This implementation simply outputs ‘pbuf’, using the trace mechanism (typically the console output).

(3) Returns the number of positive data octets transmitted (no error).


Anchor
Listing - Command
Listing - Command

Code Block
languagecpp
titleListing - Command
linenumberstrue
CPU_INT16S  App_TestCmd (CPU_INT16U        argc,                                (1)
                         CPU_CHAR         *argv[],
                         SHELL_OUT_FNCT    out_fnct,
                         SHELL_CMD_PARAM  *pcmd_param)
{
    CPU_INT16U  cmd_namd_len;
    CPU_INT16S  output;
    CPU_INT16S  ret_val;
 
 
 
    cmd_namd_len = Str_Len(argv[0]);
    output       = out_fnct(argv[0],                                            (2)
                            cmd_namd_len,
                            pcmd_param->pout_opt );
 
    switch (output) {
        case SHELL_OUT_RTN_CODE_CONN_CLOSED:
        case SHELL_OUT_ERR:
             ret_val = SHELL_EXEC_ERR;
             break;
 
        default:
             ret_val = output;
    }
   
    return (ret_val);                                                           (3)
}


Panel
bgColor#f0f0f0

(1) Function implementing a test command.

(2) Use the output function to display the command name.

(3) The return value is command specific, with the exception of SHELL_EXEC_ERR in case of an error.


Anchor
Listing - Initialization of module
Listing - Initialization of module

Code Block
languagecpp
titleListing - Initialization of module
linenumberstrue
static  SHELL_CMD  AppShellCmdTbl[] =                                          (1)
{
    {"App_test", App_TestCmd},
    {0,          0          }
};
 
 
 
void  App_InitShell (void)
{
    CPU_BOOLEAN  success;
    SHELL_ERR    err;
 
 
    APP_TRACE_DEBUG(("Initialize Shell ... "));
   
    success = Shell_Init();                                                    (2)
    if (success == DEF_OK) {
        APP_TRACE_DEBUG(("done.\n\r"));
    } else {
        APP_TRACE_DEBUG(("failed.\n\r"));
        return;
    }
 
 
    APP_TRACE_DEBUG(("Adding Shell command table ... "));
   
    Shell_CmdTblAdd("App", App_ShellAppCmdTbl, &err);                          (3)
    if (err == SHELL_ERR_NONE) {
        APP_TRACE_DEBUG(("done.\n\r"));
    } else {
        APP_TRACE_DEBUG(("failed.\n\r"));
    }
}


Panel
bgColor#f0f0f0

(1) Declare and populate a SHELL_CMD structure table that will hold the ‘App’ shell commands. The first member of this structure is the command name, and the other member a pointer to a function implementing the command itself.This command table MUST have its last entry set to ‘0’.

(2) Initializes µC/Shell internal variables.

(3) Add the AppShellCmdTbl module command table to the Shell.


µC/Shell Example Use

Once μC/Shell has been initialized, the only thing left to do it to call the Shell_Exec() function, like depicted above.

Anchor
Listing - Example use
Listing - Example use

Code Block
languagecpp
titleListing - Example use
linenumberstrue
void  App_TestShell (void)
{
    SHELL_ERR        err;
    SHELL_CMD_PARAM  cmd_param;
#if APP_FS_EN
    FS_DIR          *pdir;
#endif
 
 
    APP_TRACE_DEBUG(("Testing Shell, executing command ...\n\r"));
 
 
#if APP_FS_EN
    pdir                       = FS_OpenDir("");
    cmd_param.pcur_working_dir = (void *)pdir;
#else
    cmd_param.pcur_working_dir = (void *)0;
#endif
    cmd_param.pout_opt         = (void *)0;
 
 
    Shell_Exec( "App_test -a -b -c", &App_TestShellOut, &err);                  (1)
   
    switch (err) {
        case SHELL_ERR_NONE:
             APP_TRACE_DEBUG(("Command executed, no error.\n\r"));
             break;
 
        case SHELL_ERR_NULL_PTR:
             APP_TRACE_DEBUG(("Error, NULL pointer passed.\n\r"));
             break;
 
        case SHELL_ERR_CMD_NOT_FOUND:
             APP_TRACE_DEBUG(("Error, command NOT found.\n\r"));
             break;
 
        case SHELL_ERR_CMD_SEARCH:
             APP_TRACE_DEBUG(("Error, searching command.\n\r"));
             break;
 
        case SHELL_ERR_ARG_TBL_FULL:
             APP_TRACE_DEBUG(("Error, too many arguments\n\r"));
             break;
 
        default:
             break;
    }
}


Panel
bgColor#f0f0f0

(1) Invoke the Shell_Exec() function responsible for parsing and calling the specified command.  In this case, passing ‘App_Test’ will result in the function App_TestCmd() to be called.


µC/Shell Module Configuration

The µC/Shell module has to be configured according to your specific needs.  A template configuration file ( http-sshell_cfg.h) is included in the module package (see See Chapter 1, Directories and Files.), and this configuration file should be copied into your app_cfg.h file. and added to your project.  Here is the list of the values and description of for each of the configuration variable.  However, keep in mind that future releases of this module might include more configuration options.

Module Configuration

This value defines the TCP port µC/HTTPs will listen for requests. The default value is 80.

These values define the timeout values for sockets, in milliseconds. If the server doesn’t reply within the specified time after a request is made, that request will be aborted.

These values define the maximum number of retries for various actions before returning an error to the application.

These values determine the size of the buffer used to read the HTML file and the size of the one used to transmit this file, in bytes. If you choose to increase these values, make sure the HTTPs task’s size is large enough. If you enable the parsing of the tokens found in HTML files, you have to make sure the read buffer length ( HTTPs_CFG_FILE_RD_BUF_LEN ) is at least as large as the longest token present in your HTML files.

HTTPs_CFG_TOK_PARSE_EN allows the developer to enable or disable the parsing of the tokens found in HTML files (dynamic content). If the server does not host such content, set this configuration variable to DEF_DISABLED in order to speed up processing. The other variable defines the size of the array used to collect the tokens’ values when parsing the file. Make sure it is large enough to contain all of these values. The minimum for this value is 2.

This defines the file system root for the µC/HTTPs module.

This value defines the default file returned to web browser when no file is specified.

This value defines the message returned by µC/HTTPs to a web browser when a requested file is not found.

Static File System Module Configuration

If the static file system is being used with µC/HTTPs, the following configuration values also have to be added to your app_cfg.h file.

This value defines the maximum number of files the static file system could manage.

This value defines the maximum number of directory the static file system could manage.

This value defines the maximum file name length.

Operating System Configuration

The following configuration constants relate to the µC/HTTPs OS port. For many OSs, the µC/HTTPs task priority and stack size will need to be explicitly configured for the particular OS (consult the specific OS’s documentation for more information).

The priority of µC/HTTPs task is dependent on the requirements of the application.For µC/OS-II and µC/OS-III, the following macros must be configured within app_cfg.h :

Value of the priority for the µC/HTTPs tasks. The value assigned depend of the software architecture of your system, and of the importance of this module response time relative to the other tasks

Value of the priority for the µC/HTTPs tasks. This default value should be enough for most environments, but you should check this on your system for reliability or performance purpose.

Interface with RTOS

µC/HTTPs requires the presence of a Real Time Operating System (RTOS). As mentioned in See Directories and Files., the sample application uses µC/OS-II or µC/OS-III. It is possible to port µC/HTTPs so it is used with other OS by providing an appropriate implementation of http-s_os.c .

HTML Files Token Substitution

µC/HTTPs allows dynamic content to be inserted in HTML web pages (files having the htm or html suffix) by using special tokens being substituted before the page is actually sent to the web browser. Those tokens are represented in the HTML files as:

Assuming we have an HTML page that look like this:

When a web client requests this file, µC/HTTPs will parse the file, find the ${My_IP_Address} token, and pass the string " My_IP_Address " into the HTTPs_ValRx() callback function. That function will then substitute the token for its value, sending the following HTML file to the client:

See See µC/HTTPs API. for more information on the callback function having to be implemented to support this.

Handling Form Submissions

µC/HTTPs allows you to use forms in you HTML documents. When the form is posted, µC/HTTPs will process the POST action and will invoke the HTTPs_ValRx() callback function located in your application for every key-value pair transmitted. Please refer to See µC/HTTPs API. for more details on this function.

µC/HTTPs Example Code

The file app.c contains an example of application code, and was written to illustrate the capabilities of the µC/HTTPs module. That code simply initializes µC/OS-II or µC/OS-III, µC/TCP-IP, µC/FS, and µC/HTTPs, and creates a few tasks and other kernel objects that will give the user information about the state of the system.

Some sections of the source code have been removed or modified to help focus on the µC/HTTPs module use#define  SHELL_CFG_CMD_TBL_SIZE                            3

Size of the command module table.  Once this table is full, it is not possible to add any more command module table, unless Shell_CmdTblRem() is called.  This should be defined to the total amount of module registering command table in µC/Shell.

#define  SHELL_CFG_CMD_ARG_NBR_MAX                         5

Maximum number or argument(s) a command may pass on the string holding the complete command.

#define  SHELL_CFG_MODULE_CMD_NAME_LEN_MAX                 6

Maximum length for module command name, including the termination NUL character.

µC/Shell Internal Details

At initialization time, that is when the Shell_Init() function is called, two module command pools are being created: the free and the used.  Right after initialization, no module command are being used, so all of the SHELL_CFG_CMD_TBL_SIZE module command are located into the free pool, and the used pool is empty, like displayed below (SHELL_CFG_CMD_TBL_SIZE set to 3 in this example).

Anchor
Figure - Pools after initialization
Figure - Pools after initialization

Panel
borderWidth0
titleFigure - Pools after initialization

Image Added


Adding module command tables to the shell with Shell_CmdTblAdd() results in a free module command being taken from that pool, initialized, and taken into the used pool.  Below is a representation of the pools after two module command tables have been inserted.

Anchor
Figure - Pools after modules insertion
Figure - Pools after modules insertion

Panel
borderWidth0
titleFigure - Pools after modules insertion

Image Added


When the Shell_Exec() function is being called in order to parse a line and execute a command, the lists of module commands have to be searched to find a match.  Since the module command tables are inserted in a way analog to a stack, the search begins with the last addition.  For instance, if the ‘OS’ table has been inserted just after the ‘Net’ one, command search will always look at the ‘OS’ command table, then proceed with the ‘Net’ command table if a match has not been found.

Two searches are necessary to locate a command.  First, the correct module command table has to be found based on the command prefix, and then the corresponding command inside that table is looked for.  The second search also starts with index ‘0’ of the command table, and increments that index by ‘1’ until a match is found.

As mentionned at the beginning of this chapter, the command name and arguments passed on the command line are separated by space characters.  It is the responsibility of the commands to interpret and extract those arguments.  For instance, this command:

App_Test –a

would result in ‘-a’ to be passed as the argument for the ‘App_Test’ command.  If the dash needs to be removed, it has to be performed by the command itself.  Note however, that µC/LIB functions are available to assist with that.