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 table
typedef int (*pfnCmdLine)(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. // pfnCmdLine pfnCmd; // //! A pointer to a string of brief help text for the command. // const char *pcHelp;}tCmdLineEntry;//*****************************************************************************////! 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 table
intCmd_help(int argc, char *argv[]){ tCmdLineEntry *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. The // 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%s\n", pEntry->pcCmd, pEntry->pcHelp); // // Advance to the next entry in the table. // pEntry++; } // // Return success. // return(0);}
intCmd_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 the // 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%c%c%c%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);}
tCmdLineEntry g_sCmdTable[] ={ { "help", Cmd_help, " : Display list of commands" }, { "h", Cmd_help, " : alias for help" }, { "?", Cmd_help, " : alias for help" }, { "ls", Cmd_ls, " : Display list of files" }, { "chdir", Cmd_cd, ": Change directory" }, { "cd", Cmd_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
//*****************************************************************************//// cmdline.c - Functions to help with processing command lines.//// Copyright (c) 2007-2010 Texas Instruments Incorporated. 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 by// 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, BUT// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR 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 cmdline_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 the//! 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 CMDLINE_BAD_CMD if the command is not found,//! \b CMDLINE_TOO_MANY_ARGS if there are more arguments than can be parsed.//! Otherwise it returns the code that was returned by the command function.////*****************************************************************************intCmdLineProcess(char *pcCmdLine){ static char *argv[CMDLINE_MAX_ARGS + 1]; char *pcChar; int argc; int bFindArg = 1; tCmdLineEntry *pCmdEntry; // // Initialize the argument counter, and point to the beginning of the // 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 );