Source code is from TI Development Board
Implement shell Command Parsing on ARM
Step 1: build command implementation functions and command tables
1. Define struct and command tableCopy codeThe Code is as follows: typedef int (* pfn1_line) (int argc, char * argv []);
//************************************** ***************************************
//
//! Structure for an entry in the command list table.
//
//************************************** ***************************************
Typedef struct
{
//
//! A pointer to a string containing the name of the command.
//
Const char * pcCmd;
//
//! A function pointer to the implementation of the command.
//
Pfn1_line pfnCmd;
//
//! A pointer to a string of brief help text for the command.
//
Const char * pcHelp;
}
Tsf-lineentry;
//************************************** ***************************************
//
//! This is the command table that must be provided by the application.
//
//************************************** ***************************************
Extern tCmdLineEntry g_sCmdTable [];
2. Compile the command execution function to implement the command tableCopy codeThe Code is as follows: int
Performance_help (int argc, char * argv [])
{
Tsf-lineentry * pEntry;
//
// Print some header text.
//
UARTprintf ("\ nAvailable commands \ n ");
UARTprintf ("------------------ \ n ");
//
// Point at the beginning of the command table.
//
PEntry = & g_sCmdTable [0];
//
// Enter a loop to read each entry from the command table.
// End of the table has been reached when the command name is NULL.
//
While (pEntry-> pcCmd)
{
//
// Print the command name and the brief description.
//
UARTprintf ("% s \ n", pEntry-> pcCmd, pEntry-> pcHelp );
//
// Advance to the next entry in the table.
//
PEntry ++;
}
//
// Return success.
//
Return (0 );
}
Copy codeThe Code is as follows: int
Cmd_ls (int argc, char * argv [])
{
Unsigned long ulTotalSize;
Unsigned long ulFileCount;
Unsigned long ulDirCount;
FRESULT fresult;
FATFS * pFatFs;
//
// Open the current directory for access.
//
Fresult = f_opendir (& g_sDirObject, g_cCwdBuf );
//
// Check for error and return if there is a problem.
//
If (fresult! = FR_ OK)
{
Return (fresult );
}
UlTotalSize = 0;
UlFileCount = 0;
UlDirCount = 0;
//
// Give an extra blank line before the listing.
//
UARTprintf ("\ n ");
//
// Enter loop to enumerate through all directory entries.
//
For (;;)
{
//
// Read an entry from the directory.
//
Fresult = f_readdir (& g_sDirObject, & g_sFileInfo );
//
// Check for error and return if there is a problem.
//
If (fresult! = FR_ OK)
{
Return (fresult );
}
//
// If the file name is blank, then this is the end of
// Listing.
//
If (! G_sFileInfo.fname [0])
{
Break;
}
//
// If the attribue is directory, then increment the directory count.
//
If (g_sFileInfo.fattrib & AM_DIR)
{
UlDirCount ++;
}
//
// Otherwise, it is a file. Increment the file count, and
// Add in the file size to the total.
//
Else
{
UlFileCount ++;
UlTotalSize + = g_sFileInfo.fsize;
}
//
// Print the entry information on a single line with formatting
// To show the attributes, date, time, size, and name.
//
UARTprintf ("% c % u/% 02u/% 02u % 02u: % 02u % 9u % s \ n ",
(G_sFileInfo.fattrib & AM_DIR )? 'D ':'-',
(G_sFileInfo.fattrib & AM_RDO )? 'R ':'-',
(G_sFileInfo.fattrib & AM_HID )? 'H ':'-',
(G_sFileInfo.fattrib & AM_SYS )? 'S ':'-',
(G_sFileInfo.fattrib & AM_ARC )? 'A ':'-',
(G_sFileInfo.fdate> 9) + 1980,
(G_sFileInfo.fdate> 5) & 15,
G_sFileInfo.fdate & 31,
(G_sFileInfo.ftime> 11 ),
(G_sFileInfo.ftime> 5) & 63,
G_sFileInfo.fsize,
G_sFileInfo.fname );
// Tcp_write (Rpcb, g_sFileInfo.fname, sizeof (g_sFileInfo.fname), 0 );
} // Endfor
//
// Print summary lines showing the file, dir, and size totals.
//
UARTprintf ("\ n % 4u File (s), % 10u bytes total \ n % 4u Dir (s )",
UlFileCount, ulTotalSize, ulDirCount );
//
// Get the free space.
//
Fresult = f_getfree ("/", & ulTotalSize, & pFatFs );
//
// Check for error and return if there is a problem.
//
If (fresult! = FR_ OK)
{
Return (fresult );
}
//
// Display the amount of free space that was calculated.
//
UARTprintf (", % 10uK bytes free \ n", ulTotalSize * pFatFs-> sects_clust/2 );
//
// Made it to here, return with no errors.
//
Return (0 );
}
Copy codeThe Code is as follows: tsf-lineentry g_sCmdTable [] =
{
{"Help", Cmd_help, ": Display list of commands "},
{"H", Cmd_help, ": alias for help "},
{"? ", Pai_help,": alias for help "},
{"Ls", Cmd_ls, ": Display list of files "},
{"Chdir", Cmd_cd, ": Change directory "},
{"Cd", pai_cd, ": alias for chdir "},
{"Pwd", Cmd_pwd, ": Show current working directory "},
{"Cat", Cmd_cat, ": Show contents of a text file "},
{"Rm", CMD_Delete, ": Delete a file or a folder "},
{0, 0, 0}
};
Step 2: Compile Command Parsing and execute the Function
Copy codeThe Code is as follows: //************************************** ***************************************
//
// Define line. c-Functions to help with processing command lines.
//
// Copyright (c) 2007-2010 Texas Instruments inreceivated. All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// Exclusively on TI's microcontroller products. The software is owned
// TI and/or its suppliers, and is protected under applicable copyright
// Laws. You may not combine this software with "viral" open-source
// Software in order to form a larger program.
//
// This software is provided "as is" and with all faults.
// No warranties, whether express, implied or statutory, INCLUDING,
// Not limited to, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// A particle purpose apply to this software. ti shall not, UNDER ANY
// CIRCUMSTANCES, be liable for special, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, for any reason whatsoever.
//
// This is part of revision 6594 of the Stellaris Firmware Development Package.
//
//************************************** ***************************************
//************************************** ***************************************
//
//! \ Addtogroup extends line_api
//! @{
//
//************************************** ***************************************
# Include <string. h>
# Include "cmdline. h"
//************************************** ***************************************
//
// Defines the maximum number of arguments that can be parsed.
//
//************************************** ***************************************
# Ifndef CMDLINE_MAX_ARGS
# Define CMDLINE_MAX_ARGS 8
# Endif
//************************************** ***************************************
//
//! Process a command line string into arguments and execute the command.
//!
//! \ Param pcCmdLine points to a string that contains a command line that was
//! Obtained by an application by some means.
//!
//! This function will take the supplied command line string and break it up
//! Into individual arguments. The first argument is treated as a command and
//! Is searched for in the command table. If the command is found, then
//! Command function is called and all of the command line arguments are passed
//! In the normal argc, argv form.
//!
//! The command table is contained in an array named <tt> g_sCmdTable </tt> which
//! Must be provided by the application.
//!
//! \ Return Returns \ B release line_bad_cmd if the command is not found,
//! \ B using line_too_many_args if there are more arguments than can be parsed.
//! Otherwise it returns the code that was returned by the command function.
//
//************************************** ***************************************
Int
CmdLineProcess (char * pcCmdLine)
{
Static char * argv [CMDLINE_MAX_ARGS + 1];
Char * pcChar;
Int argc;
Int bFindArg = 1;
Tsf-lineentry * pCmdEntry;
//
// Initialize the argument counter, and point to the beginning of
// Command line string.
//
Argc = 0;
PcChar = pcCmdLine;
//
// Advance through the command line until a zero character is found.
//
While (* pcChar)
{
//
// If there is a space, then replace it with a zero, and set the flag
// To search for the next argument.
//
If (* pcChar = '')
{
* PcChar = 0;
BFindArg = 1;
}
//
// Otherwise it is not a space, so it must be a character that is part
// Of an argument.
//
Else
{
//
// If bFindArg is set, then that means we are looking for the start
// Of the next argument.
//
If (bFindArg)
{
//
// As long as the maximum number of arguments has not been
// Reached, then save the pointer to the start of this new arg
// In the argv array, and increment the count of args, argc.
//
If (argc <CMDLINE_MAX_ARGS)
{
Argv [argc] = pcChar;
Argc ++;
BFindArg = 0;
}
//
// The maximum number of arguments has been reached so return
// The error.
//
Else
{
Return (CMDLINE_TOO_MANY_ARGS );
}
}
}
//
// Advance to the next character in the command line.
//
PcChar ++;
}
//
// If one or more arguments was found, then process the command.
//
If (argc)
{
//
// Start at the beginning of the command table, to look for a matching
// Command.
//
PCmdEntry = & g_sCmdTable [0];
//
// Search through the command table until a null command string is
// Found, which marks the end of the table.
//
While (pCmdEntry-> pcCmd)
{
//
// If this command entry command string matches argv [0], then call
// The function for this command, passing the command line
// Arguments.
//
If (! Strcmp (argv [0], pCmdEntry-> pcCmd ))
{
Return (pCmdEntry-> pfnCmd (argc, argv ));
}
//
// Not found, so advance to the next entry.
//
PCmdEntry ++;
}
}
//
// Fall through to here means that no matching command was found, so return
// An error.
//
Return (CMDLINE_BAD_CMD );
}
Step 3: receive the command to call the parsing function
Receive available serial ports, etc.
If the command is received, the command is ls-l.
* Cmd = "ls-l ";
CmdLineProcess (cmd );