2 FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
\r
5 FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT
\r
6 http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
8 ***************************************************************************
\r
10 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
11 * Complete, revised, and edited pdf reference manuals are also *
\r
14 * Purchasing FreeRTOS documentation will not only help you, by *
\r
15 * ensuring you get running as quickly as possible and with an *
\r
16 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
17 * the FreeRTOS project to continue with its mission of providing *
\r
18 * professional grade, cross platform, de facto standard solutions *
\r
19 * for microcontrollers - completely free of charge! *
\r
21 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
23 * Thank you for using FreeRTOS, and thank you for your support! *
\r
25 ***************************************************************************
\r
28 This file is part of the FreeRTOS distribution.
\r
30 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
31 the terms of the GNU General Public License (version 2) as published by the
\r
32 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
34 >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to
\r
35 distribute a combined work that includes FreeRTOS without being obliged to
\r
36 provide the source code for proprietary components outside of the FreeRTOS
\r
39 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
40 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
41 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
\r
42 details. You should have received a copy of the GNU General Public License
\r
43 and the FreeRTOS license exception along with FreeRTOS; if not itcan be
\r
44 viewed here: http://www.freertos.org/a00114.html and also obtained by
\r
45 writing to Real Time Engineers Ltd., contact details for whom are available
\r
46 on the FreeRTOS WEB site.
\r
50 ***************************************************************************
\r
52 * Having a problem? Start by reading the FAQ "My application does *
\r
53 * not run, what could be wrong?" *
\r
55 * http://www.FreeRTOS.org/FAQHelp.html *
\r
57 ***************************************************************************
\r
60 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
61 license and Real Time Engineers Ltd. contact details.
\r
63 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
64 including FreeRTOS+Trace - an indispensable productivity tool, and our new
\r
65 fully thread aware and reentrant UDP/IP stack.
\r
67 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
68 Integrity Systems, who sell the code with commercial support,
\r
69 indemnification and middleware, under the OpenRTOS brand.
\r
71 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
72 engineered and independently SIL3 certified version for use in safety and
\r
73 mission critical applications that require provable dependability.
\r
76 /* FreeRTOS includes. */
\r
77 #include "FreeRTOS.h"
\r
80 /* Standard includes. */
\r
85 /* FreeRTOS+CLI includes. */
\r
86 #include "FreeRTOS_CLI.h"
\r
88 /* File system includes. */
\r
90 #include "api_mdriver_ram.h"
\r
94 #define snprintf _snprintf
\r
97 #define cliNEW_LINE "\r\n"
\r
99 /*******************************************************************************
\r
100 * See the URL in the comments within main.c for the location of the online
\r
102 ******************************************************************************/
\r
105 * Print out information on a single file.
\r
107 static void prvCreateFileInfoString( int8_t *pcBuffer, F_FIND *pxFindStruct );
\r
110 * Copies an existing file into a newly created file.
\r
112 static portBASE_TYPE prvPerformCopy( int8_t *pcSourceFile,
\r
113 int32_t lSourceFileLength,
\r
114 int8_t *pcDestinationFile,
\r
115 int8_t *pxWriteBuffer,
\r
116 size_t xWriteBufferLen );
\r
119 * Implements the DIR command.
\r
121 static portBASE_TYPE prvDIRCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString );
\r
124 * Implements the CD command.
\r
126 static portBASE_TYPE prvCDCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString );
\r
129 * Implements the DEL command.
\r
131 static portBASE_TYPE prvDELCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString );
\r
134 * Implements the TYPE command.
\r
136 static portBASE_TYPE prvTYPECommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString );
\r
139 * Implements the COPY command.
\r
141 static portBASE_TYPE prvCOPYCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString );
\r
144 * Implements the TEST command.
\r
146 static portBASE_TYPE prvTESTFSCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString );
\r
148 /* Structure that defines the DIR command line command, which lists all the
\r
149 files in the current directory. */
\r
150 static const CLI_Command_Definition_t xDIR =
\r
152 ( const int8_t * const ) "dir", /* The command string to type. */
\r
153 ( const int8_t * const ) "\r\ndir:\r\n Lists the files in the current directory\r\n",
\r
154 prvDIRCommand, /* The function to run. */
\r
155 0 /* No parameters are expected. */
\r
158 /* Structure that defines the CD command line command, which changes the
\r
159 working directory. */
\r
160 static const CLI_Command_Definition_t xCD =
\r
162 ( const int8_t * const ) "cd", /* The command string to type. */
\r
163 ( const int8_t * const ) "\r\ncd <dir name>:\r\n Changes the working directory\r\n",
\r
164 prvCDCommand, /* The function to run. */
\r
165 1 /* One parameter is expected. */
\r
168 /* Structure that defines the TYPE command line command, which prints the
\r
169 contents of a file to the console. */
\r
170 static const CLI_Command_Definition_t xTYPE =
\r
172 ( const int8_t * const ) "type", /* The command string to type. */
\r
173 ( const int8_t * const ) "\r\ntype <filename>:\r\n Prints file contents to the terminal\r\n",
\r
174 prvTYPECommand, /* The function to run. */
\r
175 1 /* One parameter is expected. */
\r
178 /* Structure that defines the DEL command line command, which deletes a file. */
\r
179 static const CLI_Command_Definition_t xDEL =
\r
181 ( const int8_t * const ) "del", /* The command string to type. */
\r
182 ( const int8_t * const ) "\r\ndel <filename>:\r\n deletes a file or directory\r\n",
\r
183 prvDELCommand, /* The function to run. */
\r
184 1 /* One parameter is expected. */
\r
187 /* Structure that defines the COPY command line command, which deletes a file. */
\r
188 static const CLI_Command_Definition_t xCOPY =
\r
190 ( const int8_t * const ) "copy", /* The command string to type. */
\r
191 ( const int8_t * const ) "\r\ncopy <source file> <dest file>:\r\n Copies <source file> to <dest file>\r\n",
\r
192 prvCOPYCommand, /* The function to run. */
\r
193 2 /* Two parameters are expected. */
\r
196 /* Structure that defines the TEST command line command, which executes some
\r
197 file system driver tests. */
\r
198 static const CLI_Command_Definition_t xTEST_FS =
\r
200 ( const int8_t * const ) "test-fs", /* The command string to type. */
\r
201 ( const int8_t * const ) "\r\ntest-fs:\r\n Executes file system tests. ALL FILES WILL BE DELETED!!!\r\n",
\r
202 prvTESTFSCommand, /* The function to run. */
\r
203 0 /* No parameters are expected. */
\r
206 /*-----------------------------------------------------------*/
\r
208 void vRegisterFileSystemCLICommands( void )
\r
210 /* Register all the command line commands defined immediately above. */
\r
211 FreeRTOS_CLIRegisterCommand( &xDIR );
\r
212 FreeRTOS_CLIRegisterCommand( &xCD );
\r
213 FreeRTOS_CLIRegisterCommand( &xTYPE );
\r
214 FreeRTOS_CLIRegisterCommand( &xDEL );
\r
215 FreeRTOS_CLIRegisterCommand( &xCOPY );
\r
216 FreeRTOS_CLIRegisterCommand( &xTEST_FS );
\r
218 /*-----------------------------------------------------------*/
\r
220 static portBASE_TYPE prvTYPECommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )
\r
222 int8_t *pcParameter;
\r
223 portBASE_TYPE xParameterStringLength, xReturn = pdTRUE;
\r
224 static F_FILE *pxFile = NULL;
\r
227 size_t xColumns = 50U;
\r
229 /* Ensure there is always a null terminator after each character written. */
\r
230 memset( pcWriteBuffer, 0x00, xWriteBufferLen );
\r
232 /* Ensure the buffer leaves space for the \r\n. */
\r
233 configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
\r
234 xWriteBufferLen -= strlen( cliNEW_LINE );
\r
236 if( xWriteBufferLen < xColumns )
\r
238 /* Ensure the loop that uses xColumns as an end condition does not
\r
239 write off the end of the buffer. */
\r
240 xColumns = xWriteBufferLen;
\r
243 if( pxFile == NULL )
\r
245 /* The file has not been opened yet. Find the file name. */
\r
246 pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter
\r
248 pcCommandString, /* The command string itself. */
\r
249 1, /* Return the first parameter. */
\r
250 &xParameterStringLength /* Store the parameter string length. */
\r
253 /* Sanity check something was returned. */
\r
254 configASSERT( pcParameter );
\r
256 /* Attempt to open the requested file. */
\r
257 pxFile = f_open( ( const char * ) pcParameter, "r" );
\r
260 if( pxFile != NULL )
\r
262 /* Read the next chunk of data from the file. */
\r
263 for( xByte = 0; xByte < xColumns; xByte++ )
\r
265 iChar = f_getc( pxFile );
\r
269 /* No more characters to return. */
\r
276 pcWriteBuffer[ xByte ] = ( int8_t ) iChar;
\r
281 if( pxFile == NULL )
\r
283 /* Either the file was not opened, or all the data from the file has
\r
284 been returned and the file is now closed. */
\r
288 strcat( ( char * ) pcWriteBuffer, cliNEW_LINE );
\r
292 /*-----------------------------------------------------------*/
\r
294 static portBASE_TYPE prvCDCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )
\r
296 int8_t *pcParameter;
\r
297 portBASE_TYPE xParameterStringLength;
\r
298 unsigned char ucReturned;
\r
299 size_t xStringLength;
\r
301 /* Obtain the parameter string. */
\r
302 pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter
\r
304 pcCommandString, /* The command string itself. */
\r
305 1, /* Return the first parameter. */
\r
306 &xParameterStringLength /* Store the parameter string length. */
\r
309 /* Sanity check something was returned. */
\r
310 configASSERT( pcParameter );
\r
312 /* Attempt to move to the requested directory. */
\r
313 ucReturned = f_chdir( ( char * ) pcParameter );
\r
315 if( ucReturned == F_NO_ERROR )
\r
317 sprintf( ( char * ) pcWriteBuffer, "In: " );
\r
318 xStringLength = strlen( ( const char * ) pcWriteBuffer );
\r
319 f_getcwd( ( char * ) &( pcWriteBuffer[ xStringLength ] ), ( unsigned char ) ( xWriteBufferLen - xStringLength ) );
\r
323 sprintf( ( char * ) pcWriteBuffer, "Error" );
\r
326 strcat( ( char * ) pcWriteBuffer, cliNEW_LINE );
\r
330 /*-----------------------------------------------------------*/
\r
332 static portBASE_TYPE prvDIRCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )
\r
334 static F_FIND *pxFindStruct = NULL;
\r
335 unsigned char ucReturned;
\r
336 portBASE_TYPE xReturn = pdFALSE;
\r
338 /* This assumes pcWriteBuffer is long enough. */
\r
339 ( void ) pcCommandString;
\r
341 /* Ensure the buffer leaves space for the \r\n. */
\r
342 configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
\r
343 xWriteBufferLen -= strlen( cliNEW_LINE );
\r
345 if( pxFindStruct == NULL )
\r
347 /* This is the first time this function has been executed since the Dir
\r
348 command was run. Create the find structure. */
\r
349 pxFindStruct = ( F_FIND * ) pvPortMalloc( sizeof( F_FIND ) );
\r
351 if( pxFindStruct != NULL )
\r
353 ucReturned = f_findfirst( "*.*", pxFindStruct );
\r
355 if( ucReturned == F_NO_ERROR )
\r
357 prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
\r
362 snprintf( ( char * ) pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." );
\r
367 snprintf( ( char * ) pcWriteBuffer, xWriteBufferLen, "Failed to allocate RAM (using heap_4.c will prevent fragmentation)." );
\r
372 /* The find struct has already been created. Find the next file in
\r
374 ucReturned = f_findnext( pxFindStruct );
\r
376 if( ucReturned == F_NO_ERROR )
\r
378 prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
\r
383 /* There are no more files. Free the find structure. */
\r
384 vPortFree( pxFindStruct );
\r
385 pxFindStruct = NULL;
\r
387 /* No string to return. */
\r
388 pcWriteBuffer[ 0 ] = 0x00;
\r
392 strcat( ( char * ) pcWriteBuffer, cliNEW_LINE );
\r
396 /*-----------------------------------------------------------*/
\r
398 static portBASE_TYPE prvDELCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )
\r
400 int8_t *pcParameter;
\r
401 portBASE_TYPE xParameterStringLength;
\r
402 unsigned char ucReturned;
\r
404 /* This function assumes xWriteBufferLen is large enough! */
\r
405 ( void ) xWriteBufferLen;
\r
407 /* Obtain the parameter string. */
\r
408 pcParameter = ( int8_t * ) FreeRTOS_CLIGetParameter
\r
410 pcCommandString, /* The command string itself. */
\r
411 1, /* Return the first parameter. */
\r
412 &xParameterStringLength /* Store the parameter string length. */
\r
415 /* Sanity check something was returned. */
\r
416 configASSERT( pcParameter );
\r
418 /* Attempt to delete the file. */
\r
419 ucReturned = f_delete( ( const char * ) pcParameter );
\r
421 if( ucReturned == F_NO_ERROR )
\r
423 sprintf( ( char * ) pcWriteBuffer, "%s was deleted", pcParameter );
\r
427 sprintf( ( char * ) pcWriteBuffer, "Error" );
\r
430 strcat( ( char * ) pcWriteBuffer, cliNEW_LINE );
\r
434 /*-----------------------------------------------------------*/
\r
436 static portBASE_TYPE prvTESTFSCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )
\r
438 unsigned portBASE_TYPE uxOriginalPriority;
\r
440 /* Avoid compiler warnings. */
\r
441 ( void ) xWriteBufferLen;
\r
442 ( void ) pcCommandString;
\r
444 /* Limitations in the interaction with the Windows TCP/IP stack require
\r
445 the command console to run at the idle priority. Raise the priority for
\r
446 the duration of the tests to ensure there are not multiple switches to the
\r
447 idle task as in the simulated environment the idle task hook function may
\r
448 include a (relatively) long delay. */
\r
449 uxOriginalPriority = uxTaskPriorityGet( NULL );
\r
450 vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
\r
454 /* Reset back to the original priority. */
\r
455 vTaskPrioritySet( NULL, uxOriginalPriority );
\r
457 sprintf( ( char * ) pcWriteBuffer, "%s", "Test results were sent to Windows console" );
\r
461 /*-----------------------------------------------------------*/
\r
463 static portBASE_TYPE prvCOPYCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )
\r
465 int8_t *pcSourceFile, *pcDestinationFile;
\r
466 portBASE_TYPE xParameterStringLength;
\r
467 long lSourceLength, lDestinationLength = 0;
\r
469 /* Obtain the name of the destination file. */
\r
470 pcDestinationFile = ( int8_t * ) FreeRTOS_CLIGetParameter
\r
472 pcCommandString, /* The command string itself. */
\r
473 2, /* Return the second parameter. */
\r
474 &xParameterStringLength /* Store the parameter string length. */
\r
477 /* Sanity check something was returned. */
\r
478 configASSERT( pcDestinationFile );
\r
480 /* Obtain the name of the source file. */
\r
481 pcSourceFile = ( int8_t * ) FreeRTOS_CLIGetParameter
\r
483 pcCommandString, /* The command string itself. */
\r
484 1, /* Return the first parameter. */
\r
485 &xParameterStringLength /* Store the parameter string length. */
\r
488 /* Sanity check something was returned. */
\r
489 configASSERT( pcSourceFile );
\r
491 /* Terminate the string. */
\r
492 pcSourceFile[ xParameterStringLength ] = 0x00;
\r
494 /* See if the source file exists, obtain its length if it does. */
\r
495 lSourceLength = f_filelength( ( const char * ) pcSourceFile );
\r
497 if( lSourceLength == 0 )
\r
499 sprintf( ( char * ) pcWriteBuffer, "Source file does not exist" );
\r
503 /* See if the destination file exists. */
\r
504 lDestinationLength = f_filelength( ( const char * ) pcDestinationFile );
\r
506 if( lDestinationLength != 0 )
\r
508 sprintf( ( char * ) pcWriteBuffer, "Error: Destination file already exists" );
\r
512 /* Continue only if the source file exists and the destination file does
\r
514 if( ( lSourceLength != 0 ) && ( lDestinationLength == 0 ) )
\r
516 if( prvPerformCopy( pcSourceFile, lSourceLength, pcDestinationFile, pcWriteBuffer, xWriteBufferLen ) == pdPASS )
\r
518 sprintf( ( char * ) pcWriteBuffer, "Copy made" );
\r
522 sprintf( ( char * ) pcWriteBuffer, "Error during copy" );
\r
526 strcat( ( char * ) pcWriteBuffer, cliNEW_LINE );
\r
530 /*-----------------------------------------------------------*/
\r
532 static portBASE_TYPE prvPerformCopy( int8_t *pcSourceFile,
\r
533 int32_t lSourceFileLength,
\r
534 int8_t *pcDestinationFile,
\r
535 int8_t *pxWriteBuffer,
\r
536 size_t xWriteBufferLen )
\r
538 int32_t lBytesRead = 0, lBytesToRead, lBytesRemaining;
\r
540 portBASE_TYPE xReturn = pdPASS;
\r
542 /* NOTE: Error handling has been omitted for clarity. */
\r
544 while( lBytesRead < lSourceFileLength )
\r
546 /* How many bytes are left? */
\r
547 lBytesRemaining = lSourceFileLength - lBytesRead;
\r
549 /* How many bytes should be read this time around the loop. Can't
\r
550 read more bytes than will fit into the buffer. */
\r
551 if( lBytesRemaining > ( long ) xWriteBufferLen )
\r
553 lBytesToRead = ( long ) xWriteBufferLen;
\r
557 lBytesToRead = lBytesRemaining;
\r
560 /* Open the source file, seek past the data that has already been
\r
561 read from the file, read the next block of data, then close the
\r
562 file again so the destination file can be opened. */
\r
563 pxFile = f_open( ( const char * ) pcSourceFile, "r" );
\r
564 if( pxFile != NULL )
\r
566 f_seek( pxFile, lBytesRead, F_SEEK_SET );
\r
567 f_read( pxWriteBuffer, lBytesToRead, 1, pxFile );
\r
576 /* Open the destination file and write the block of data to the end of
\r
578 pxFile = f_open( ( const char * ) pcDestinationFile, "a" );
\r
579 if( pxFile != NULL )
\r
581 f_write( pxWriteBuffer, lBytesToRead, 1, pxFile );
\r
590 lBytesRead += lBytesToRead;
\r
595 /*-----------------------------------------------------------*/
\r
597 static void prvCreateFileInfoString( int8_t *pcBuffer, F_FIND *pxFindStruct )
\r
599 const char *pcWritableFile = "writable file", *pcReadOnlyFile = "read only file", *pcDirectory = "directory";
\r
600 const char * pcAttrib;
\r
602 /* Point pcAttrib to a string that describes the file. */
\r
603 if( ( pxFindStruct->attr & F_ATTR_DIR ) != 0 )
\r
605 pcAttrib = pcDirectory;
\r
607 else if( pxFindStruct->attr & F_ATTR_READONLY )
\r
609 pcAttrib = pcReadOnlyFile;
\r
613 pcAttrib = pcWritableFile;
\r
616 /* Create a string that includes the file name, the file size and the
\r
617 attributes string. */
\r
618 sprintf( ( char * ) pcBuffer, "%s [%s] [size=%d]", pxFindStruct->filename, pcAttrib, pxFindStruct->filesize );
\r