]> git.sur5r.net Git - freertos/blob
147f185775f026ef4215d8e5b16d0612e789e37b
[freertos] /
1 /*\r
2     FreeRTOS V8.0.1 - Copyright (C) 2014 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \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
7 \r
8     ***************************************************************************\r
9      *                                                                       *\r
10      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
11      *    Complete, revised, and edited pdf reference manuals are also       *\r
12      *    available.                                                         *\r
13      *                                                                       *\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
20      *                                                                       *\r
21      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
22      *                                                                       *\r
23      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
24      *                                                                       *\r
25     ***************************************************************************\r
26 \r
27 \r
28     This file is part of the FreeRTOS distribution.\r
29 \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
33 \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
37     kernel.\r
38 \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
47 \r
48     1 tab == 4 spaces!\r
49 \r
50     ***************************************************************************\r
51      *                                                                       *\r
52      *    Having a problem?  Start by reading the FAQ "My application does   *\r
53      *    not run, what could be wrong?"                                     *\r
54      *                                                                       *\r
55      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
56      *                                                                       *\r
57     ***************************************************************************\r
58 \r
59 \r
60     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
61     license and Real Time Engineers Ltd. contact details.\r
62 \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
66 \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
70 \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
74 */\r
75 \r
76 /* FreeRTOS includes. */\r
77 #include "FreeRTOS.h"\r
78 #include "task.h"\r
79 \r
80 /* Standard includes. */\r
81 #include <stdint.h>\r
82 #include <stdio.h>\r
83 #include <stdlib.h>\r
84 #include <string.h>\r
85 \r
86 /* FreeRTOS+CLI includes. */\r
87 #include "FreeRTOS_CLI.h"\r
88 \r
89 /* File system includes. */\r
90 #include "fat_sl.h"\r
91 #include "api_mdriver_ram.h"\r
92 \r
93 #ifdef _WINDOWS_\r
94         #define snprintf _snprintf\r
95 #endif\r
96 \r
97 #define cliNEW_LINE             "\r\n"\r
98 \r
99 /*******************************************************************************\r
100  * See the URL in the comments within main.c for the location of the online\r
101  * documentation.\r
102  ******************************************************************************/\r
103 \r
104 /*\r
105  * Print out information on a single file.\r
106  */\r
107 static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct );\r
108 \r
109 /*\r
110  * Copies an existing file into a newly created file.\r
111  */\r
112 static portBASE_TYPE prvPerformCopy( const char *pcSourceFile,\r
113                                                                         int32_t lSourceFileLength,\r
114                                                                         const char *pcDestinationFile,\r
115                                                                         char *pxWriteBuffer,\r
116                                                                         size_t xWriteBufferLen );\r
117 \r
118 /*\r
119  * Implements the DIR command.\r
120  */\r
121 static portBASE_TYPE prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
122 \r
123 /*\r
124  * Implements the CD command.\r
125  */\r
126 static portBASE_TYPE prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
127 \r
128 /*\r
129  * Implements the DEL command.\r
130  */\r
131 static portBASE_TYPE prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
132 \r
133 /*\r
134  * Implements the TYPE command.\r
135  */\r
136 static portBASE_TYPE prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
137 \r
138 /*\r
139  * Implements the COPY command.\r
140  */\r
141 static portBASE_TYPE prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
142 \r
143 /* Structure that defines the DIR command line command, which lists all the\r
144 files in the current directory. */\r
145 static const CLI_Command_Definition_t xDIR =\r
146 {\r
147         "dir", /* The command string to type. */\r
148         "\r\ndir:\r\n Lists the files in the current directory\r\n",\r
149         prvDIRCommand, /* The function to run. */\r
150         0 /* No parameters are expected. */\r
151 };\r
152 \r
153 /* Structure that defines the CD command line command, which changes the\r
154 working directory. */\r
155 static const CLI_Command_Definition_t xCD =\r
156 {\r
157         "cd", /* The command string to type. */\r
158         "\r\ncd <dir name>:\r\n Changes the working directory\r\n",\r
159         prvCDCommand, /* The function to run. */\r
160         1 /* One parameter is expected. */\r
161 };\r
162 \r
163 /* Structure that defines the TYPE command line command, which prints the\r
164 contents of a file to the console. */\r
165 static const CLI_Command_Definition_t xTYPE =\r
166 {\r
167         "type", /* The command string to type. */\r
168         "\r\ntype <filename>:\r\n Prints file contents to the terminal\r\n",\r
169         prvTYPECommand, /* The function to run. */\r
170         1 /* One parameter is expected. */\r
171 };\r
172 \r
173 /* Structure that defines the DEL command line command, which deletes a file. */\r
174 static const CLI_Command_Definition_t xDEL =\r
175 {\r
176         "del", /* The command string to type. */\r
177         "\r\ndel <filename>:\r\n deletes a file or directory\r\n",\r
178         prvDELCommand, /* The function to run. */\r
179         1 /* One parameter is expected. */\r
180 };\r
181 \r
182 /* Structure that defines the COPY command line command, which deletes a file. */\r
183 static const CLI_Command_Definition_t xCOPY =\r
184 {\r
185         "copy", /* The command string to type. */\r
186         "\r\ncopy <source file> <dest file>:\r\n Copies <source file> to <dest file>\r\n",\r
187         prvCOPYCommand, /* The function to run. */\r
188         2 /* Two parameters are expected. */\r
189 };\r
190 \r
191 /*-----------------------------------------------------------*/\r
192 \r
193 void vRegisterFileSystemCLICommands( void )\r
194 {\r
195         /* Register all the command line commands defined immediately above. */\r
196         FreeRTOS_CLIRegisterCommand( &xDIR );\r
197         FreeRTOS_CLIRegisterCommand( &xCD );\r
198         FreeRTOS_CLIRegisterCommand( &xTYPE );\r
199         FreeRTOS_CLIRegisterCommand( &xDEL );\r
200         FreeRTOS_CLIRegisterCommand( &xCOPY );\r
201 }\r
202 /*-----------------------------------------------------------*/\r
203 \r
204 static portBASE_TYPE prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
205 {\r
206 const char *pcParameter;\r
207 portBASE_TYPE xParameterStringLength, xReturn = pdTRUE;\r
208 static F_FILE *pxFile = NULL;\r
209 int iChar;\r
210 size_t xByte;\r
211 size_t xColumns = 50U;\r
212 \r
213         /* Ensure there is always a null terminator after each character written. */\r
214         memset( pcWriteBuffer, 0x00, xWriteBufferLen );\r
215 \r
216         /* Ensure the buffer leaves space for the \r\n. */\r
217         configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );\r
218         xWriteBufferLen -= strlen( cliNEW_LINE );\r
219 \r
220         if( xWriteBufferLen < xColumns )\r
221         {\r
222                 /* Ensure the loop that uses xColumns as an end condition does not\r
223                 write off the end of the buffer. */\r
224                 xColumns = xWriteBufferLen;\r
225         }\r
226 \r
227         if( pxFile == NULL )\r
228         {\r
229                 /* The file has not been opened yet.  Find the file name. */\r
230                 pcParameter = FreeRTOS_CLIGetParameter\r
231                                                         (\r
232                                                                 pcCommandString,                /* The command string itself. */\r
233                                                                 1,                                              /* Return the first parameter. */\r
234                                                                 &xParameterStringLength /* Store the parameter string length. */\r
235                                                         );\r
236 \r
237                 /* Sanity check something was returned. */\r
238                 configASSERT( pcParameter );\r
239 \r
240                 /* Attempt to open the requested file. */\r
241                 pxFile = f_open( pcParameter, "r" );\r
242         }\r
243 \r
244         if( pxFile != NULL )\r
245         {\r
246                 /* Read the next chunk of data from the file. */\r
247                 for( xByte = 0; xByte < xColumns; xByte++ )\r
248                 {\r
249                         iChar = f_getc( pxFile );\r
250 \r
251                         if( iChar == -1 )\r
252                         {\r
253                                 /* No more characters to return. */\r
254                                 f_close( pxFile );\r
255                                 pxFile = NULL;\r
256                                 break;\r
257                         }\r
258                         else\r
259                         {\r
260                                 pcWriteBuffer[ xByte ] = ( char ) iChar;\r
261                         }\r
262                 }\r
263         }\r
264 \r
265         if( pxFile == NULL )\r
266         {\r
267                 /* Either the file was not opened, or all the data from the file has\r
268                 been returned and the file is now closed. */\r
269                 xReturn = pdFALSE;\r
270         }\r
271 \r
272         strcat( pcWriteBuffer, cliNEW_LINE );\r
273 \r
274         return xReturn;\r
275 }\r
276 /*-----------------------------------------------------------*/\r
277 \r
278 static portBASE_TYPE prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
279 {\r
280 const char *pcParameter;\r
281 portBASE_TYPE xParameterStringLength;\r
282 unsigned char ucReturned;\r
283 size_t xStringLength;\r
284 \r
285         /* Obtain the parameter string. */\r
286         pcParameter = FreeRTOS_CLIGetParameter\r
287                                                 (\r
288                                                         pcCommandString,                /* The command string itself. */\r
289                                                         1,                                              /* Return the first parameter. */\r
290                                                         &xParameterStringLength /* Store the parameter string length. */\r
291                                                 );\r
292 \r
293         /* Sanity check something was returned. */\r
294         configASSERT( pcParameter );\r
295 \r
296         /* Attempt to move to the requested directory. */\r
297         ucReturned = f_chdir( pcParameter );\r
298 \r
299         if( ucReturned == F_NO_ERROR )\r
300         {\r
301                 sprintf( pcWriteBuffer, "In: " );\r
302                 xStringLength = strlen( pcWriteBuffer );\r
303                 f_getcwd( &( pcWriteBuffer[ xStringLength ] ), ( unsigned char ) ( xWriteBufferLen - xStringLength ) );\r
304         }\r
305         else\r
306         {\r
307                 sprintf( pcWriteBuffer, "Error" );\r
308         }\r
309 \r
310         strcat( pcWriteBuffer, cliNEW_LINE );\r
311 \r
312         return pdFALSE;\r
313 }\r
314 /*-----------------------------------------------------------*/\r
315 \r
316 static portBASE_TYPE prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
317 {\r
318 static F_FIND *pxFindStruct = NULL;\r
319 unsigned char ucReturned;\r
320 portBASE_TYPE xReturn = pdFALSE;\r
321 \r
322         /* This assumes pcWriteBuffer is long enough. */\r
323         ( void ) pcCommandString;\r
324 \r
325         /* Ensure the buffer leaves space for the \r\n. */\r
326         configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );\r
327         xWriteBufferLen -= strlen( cliNEW_LINE );\r
328 \r
329         if( pxFindStruct == NULL )\r
330         {\r
331                 /* This is the first time this function has been executed since the Dir\r
332                 command was run.  Create the find structure. */\r
333                 pxFindStruct = ( F_FIND * ) pvPortMalloc( sizeof( F_FIND ) );\r
334 \r
335                 if( pxFindStruct != NULL )\r
336                 {\r
337                         ucReturned = f_findfirst( "*.*", pxFindStruct );\r
338 \r
339                         if( ucReturned == F_NO_ERROR )\r
340                         {\r
341                                 prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );\r
342                                 xReturn = pdPASS;\r
343                         }\r
344                         else\r
345                         {\r
346                                 snprintf( pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." );\r
347                         }\r
348                 }\r
349                 else\r
350                 {\r
351                         snprintf( pcWriteBuffer, xWriteBufferLen, "Failed to allocate RAM (using heap_4.c will prevent fragmentation)." );\r
352                 }\r
353         }\r
354         else\r
355         {\r
356                 /* The find struct has already been created.  Find the next file in\r
357                 the directory. */\r
358                 ucReturned = f_findnext( pxFindStruct );\r
359 \r
360                 if( ucReturned == F_NO_ERROR )\r
361                 {\r
362                         prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );\r
363                         xReturn = pdPASS;\r
364                 }\r
365                 else\r
366                 {\r
367                         /* There are no more files.  Free the find structure. */\r
368                         vPortFree( pxFindStruct );\r
369                         pxFindStruct = NULL;\r
370 \r
371                         /* No string to return. */\r
372                         pcWriteBuffer[ 0 ] = 0x00;\r
373                 }\r
374         }\r
375 \r
376         strcat( pcWriteBuffer, cliNEW_LINE );\r
377 \r
378         return xReturn;\r
379 }\r
380 /*-----------------------------------------------------------*/\r
381 \r
382 static portBASE_TYPE prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
383 {\r
384 const char *pcParameter;\r
385 portBASE_TYPE xParameterStringLength;\r
386 unsigned char ucReturned;\r
387 \r
388         /* This function assumes xWriteBufferLen is large enough! */\r
389         ( void ) xWriteBufferLen;\r
390 \r
391         /* Obtain the parameter string. */\r
392         pcParameter = FreeRTOS_CLIGetParameter\r
393                                                 (\r
394                                                         pcCommandString,                /* The command string itself. */\r
395                                                         1,                                              /* Return the first parameter. */\r
396                                                         &xParameterStringLength /* Store the parameter string length. */\r
397                                                 );\r
398 \r
399         /* Sanity check something was returned. */\r
400         configASSERT( pcParameter );\r
401 \r
402         /* Attempt to delete the file. */\r
403         ucReturned = f_delete( pcParameter );\r
404 \r
405         if( ucReturned == F_NO_ERROR )\r
406         {\r
407                 sprintf( pcWriteBuffer, "%s was deleted", pcParameter );\r
408         }\r
409         else\r
410         {\r
411                 sprintf( pcWriteBuffer, "Error" );\r
412         }\r
413 \r
414         strcat( pcWriteBuffer, cliNEW_LINE );\r
415 \r
416         return pdFALSE;\r
417 }\r
418 /*-----------------------------------------------------------*/\r
419 \r
420 static portBASE_TYPE prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
421 {\r
422 const char *pcDestinationFile;\r
423 char *pcSourceFile;\r
424 portBASE_TYPE xParameterStringLength;\r
425 long lSourceLength, lDestinationLength = 0;\r
426 \r
427         /* Obtain the name of the destination file. */\r
428         pcDestinationFile = FreeRTOS_CLIGetParameter\r
429                                                         (\r
430                                                                 pcCommandString,                /* The command string itself. */\r
431                                                                 2,                                              /* Return the second parameter. */\r
432                                                                 &xParameterStringLength /* Store the parameter string length. */\r
433                                                         );\r
434 \r
435         /* Sanity check something was returned. */\r
436         configASSERT( pcDestinationFile );\r
437 \r
438         /* Obtain the name of the source file. */\r
439         pcSourceFile = ( char * ) FreeRTOS_CLIGetParameter\r
440                                                                 (\r
441                                                                         pcCommandString,                /* The command string itself. */\r
442                                                                         1,                                              /* Return the first parameter. */\r
443                                                                         &xParameterStringLength /* Store the parameter string length. */\r
444                                                                 );\r
445 \r
446         /* Sanity check something was returned. */\r
447         configASSERT( pcSourceFile );\r
448 \r
449         /* Terminate the string. */\r
450         pcSourceFile[ xParameterStringLength ] = 0x00;\r
451 \r
452         /* See if the source file exists, obtain its length if it does. */\r
453         lSourceLength = f_filelength( pcSourceFile );\r
454 \r
455         if( lSourceLength == 0 )\r
456         {\r
457                 sprintf( pcWriteBuffer, "Source file does not exist" );\r
458         }\r
459         else\r
460         {\r
461                 /* See if the destination file exists. */\r
462                 lDestinationLength = f_filelength( pcDestinationFile );\r
463 \r
464                 if( lDestinationLength != 0 )\r
465                 {\r
466                         sprintf( pcWriteBuffer, "Error: Destination file already exists" );\r
467                 }\r
468         }\r
469 \r
470         /* Continue only if the source file exists and the destination file does\r
471         not exist. */\r
472         if( ( lSourceLength != 0 ) && ( lDestinationLength == 0 ) )\r
473         {\r
474                 if( prvPerformCopy( pcSourceFile, lSourceLength, pcDestinationFile, pcWriteBuffer, xWriteBufferLen ) == pdPASS )\r
475                 {\r
476                         sprintf( pcWriteBuffer, "Copy made" );\r
477                 }\r
478                 else\r
479                 {\r
480                         sprintf( pcWriteBuffer, "Error during copy" );\r
481                 }\r
482         }\r
483 \r
484         strcat( pcWriteBuffer, cliNEW_LINE );\r
485 \r
486         return pdFALSE;\r
487 }\r
488 /*-----------------------------------------------------------*/\r
489 \r
490 static portBASE_TYPE prvPerformCopy( const char *pcSourceFile,\r
491                                                                         int32_t lSourceFileLength,\r
492                                                                         const char *pcDestinationFile,\r
493                                                                         char *pxWriteBuffer,\r
494                                                                         size_t xWriteBufferLen )\r
495 {\r
496 int32_t lBytesRead = 0, lBytesToRead, lBytesRemaining;\r
497 F_FILE *pxFile;\r
498 portBASE_TYPE xReturn = pdPASS;\r
499 \r
500         /* NOTE:  Error handling has been omitted for clarity. */\r
501 \r
502         while( lBytesRead < lSourceFileLength )\r
503         {\r
504                 /* How many bytes are left? */\r
505                 lBytesRemaining = lSourceFileLength - lBytesRead;\r
506 \r
507                 /* How many bytes should be read this time around the loop.  Can't\r
508                 read more bytes than will fit into the buffer. */\r
509                 if( lBytesRemaining > ( long ) xWriteBufferLen )\r
510                 {\r
511                         lBytesToRead = ( long ) xWriteBufferLen;\r
512                 }\r
513                 else\r
514                 {\r
515                         lBytesToRead = lBytesRemaining;\r
516                 }\r
517 \r
518                 /* Open the source file, seek past the data that has already been\r
519                 read from the file, read the next block of data, then close the\r
520                 file again so the destination file can be opened. */\r
521                 pxFile = f_open( pcSourceFile, "r" );\r
522                 if( pxFile != NULL )\r
523                 {\r
524                         f_seek( pxFile, lBytesRead, F_SEEK_SET );\r
525                         f_read( pxWriteBuffer, lBytesToRead, 1, pxFile );\r
526                         f_close( pxFile );\r
527                 }\r
528                 else\r
529                 {\r
530                         xReturn = pdFAIL;\r
531                         break;\r
532                 }\r
533 \r
534                 /* Open the destination file and write the block of data to the end of\r
535                 the file. */\r
536                 pxFile = f_open( pcDestinationFile, "a" );\r
537                 if( pxFile != NULL )\r
538                 {\r
539                         f_write( pxWriteBuffer, lBytesToRead, 1, pxFile );\r
540                         f_close( pxFile );\r
541                 }\r
542                 else\r
543                 {\r
544                         xReturn = pdFAIL;\r
545                         break;\r
546                 }\r
547 \r
548                 lBytesRead += lBytesToRead;\r
549         }\r
550 \r
551         return xReturn;\r
552 }\r
553 /*-----------------------------------------------------------*/\r
554 \r
555 static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct )\r
556 {\r
557 const char *pcWritableFile = "writable file", *pcReadOnlyFile = "read only file", *pcDirectory = "directory";\r
558 const char * pcAttrib;\r
559 \r
560         /* Point pcAttrib to a string that describes the file. */\r
561         if( ( pxFindStruct->attr & F_ATTR_DIR ) != 0 )\r
562         {\r
563                 pcAttrib = pcDirectory;\r
564         }\r
565         else if( pxFindStruct->attr & F_ATTR_READONLY )\r
566         {\r
567                 pcAttrib = pcReadOnlyFile;\r
568         }\r
569         else\r
570         {\r
571                 pcAttrib = pcWritableFile;\r
572         }\r
573 \r
574         /* Create a string that includes the file name, the file size and the\r
575         attributes string. */\r
576         sprintf( pcBuffer, "%s [%s] [size=%d]", pxFindStruct->filename, pcAttrib, ( int ) pxFindStruct->filesize );\r
577 }\r