Several examples run on only mbed-os5.13.0 (not 5.14.0)

Dependencies:   BD_SD_DISCO_F769NI BSP_DISCO_F769NI LCD_DISCO_F769NI TS_DISCO_F769NI USBHost_F769NI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mon.cpp Source File

mon.cpp

00001 /*
00002  * mbed Application program for the mbed
00003  *  FatFs Check program / monitor part
00004  *
00005  * Copyright (c) 2015,'18 Kenji Arai / JH1PJL
00006  *  http://www.page.sannet.ne.jp/kenjia/index.html
00007  *  https://os.mbed.com/users/kenjiArai/
00008  *      Created:    May        5th, 2015
00009  *      Revised:    June      14th, 2015
00010  *      Revised:    April      7th, 2018
00011  */
00012 
00013 /*
00014  *---------------- REFERENCE ---------------------------------------------------
00015  * Original Source Information
00016  * FatFs sample program
00017  *      ChaN FatFs  http://elm-chan.org/
00018  *      http://elm-chan.org/fsw/ff/00index_e.html
00019  */
00020 /*----------------------------------------------------------------------*/
00021 /* FAT file system sample project for FatFs            (C)ChaN, 2016    */
00022 /*----------------------------------------------------------------------*/
00023 
00024 //  Include --------------------------------------------------------------------
00025 #include "mbed.h"
00026 #if (MBED_MAJOR_VERSION == 2)
00027 #include "SDFileSystem.h"
00028 #elif (MBED_MAJOR_VERSION == 5)
00029 #include "FATFileSystem.h"
00030 #endif
00031 #include "ff.h"
00032 #include "ffconf.h"
00033 #include "diskio.h"
00034 #include "mon.h"
00035 
00036 //  Definition -----------------------------------------------------------------
00037 #define DO_DEBUG    0
00038 
00039 #if DO_DEBUG
00040 #define DEBUG_LINE  pc.printf("line:%d\r\n", __LINE__);
00041 #else
00042 #define DEBUG_LINE  {;}
00043 #endif
00044 
00045 // Com
00046 #if  1
00047 #define BAUD(x)     pc.baud(x)
00048 #define GETC(x)     pc.getc(x)
00049 #define PUTC(x)     pc.putc(x)
00050 #define PUTS(x)     pc.puts(x)
00051 #define PRINTF(...) pc.printf(__VA_ARGS__)
00052 #define READABLE(x) pc.readable(x)
00053 #else
00054 #define BAUD(x)     {;}
00055 #define GETC(x)     {;}
00056 #define PUTC(x)     {;}
00057 #define PRINTF(...) {;}
00058 #define READABLE(x) {;}
00059 #endif
00060 
00061 #define UTC_JST_OFFSET  (32400) // +9 hours
00062 
00063 // from ffconf.h
00064 #define _VOLUMES    1
00065 #define FF_USE_LFN  0
00066 
00067 #if !defined(FF_FS_RPATH)
00068 #define FF_FS_RPATH 0
00069 #endif
00070 
00071 #define DW_CHAR         sizeof(char)
00072 #define DW_SHORT        sizeof(short)
00073 #define DW_LONG         sizeof(long)
00074 
00075 /* These types must be 16-bit, 32-bit or larger integer */
00076 typedef int             INT;
00077 typedef unsigned int    UINT;
00078 
00079 /* These types must be 8-bit integer */
00080 typedef char            CHAR;
00081 typedef unsigned char   UCHAR;
00082 typedef unsigned char   BYTE;
00083 
00084 /* These types must be 16-bit integer */
00085 typedef short           SHORT;
00086 typedef unsigned short  USHORT;
00087 typedef unsigned short  WORD;
00088 typedef unsigned short  WCHAR;
00089 
00090 /* These types must be 32-bit integer */
00091 typedef long            LONG;
00092 typedef unsigned long   ULONG;
00093 typedef unsigned long   DWORD;
00094 /*  by Kenji Arai / JH1PJL  September 10th, 2012  */
00095 typedef unsigned long long  DDWORD;
00096 
00097 //  RAM ------------------------------------------------------------------------
00098 BYTE Buff[4096];
00099 char Linebuf[128];          // Console input buffer
00100 FATFS Fatfs[_VOLUMES];      // File system object for each logical drive
00101 FIL File1, File2;           // File objects
00102 FATFS_DIR* Dirx;
00103 FILINFO Finfo;
00104 #if FF_USE_LFN
00105 //inside of FILINFO
00106 char Lfname[512];
00107 #endif
00108 DWORD AccSize;              // Work register for fs command
00109 WORD AccFiles, AccDirs;
00110 
00111 //  ROM / Constant data --------------------------------------------------------
00112 char *const monmsg0 = "Start monitor program for FatFs File System\r\n";
00113 char *const monmsg1 = " <Please press any key to start the monitor>";
00114 
00115 static const char HelpMsg0[] =
00116     "dir   <full_pass>\r\n"
00117     "type  <file_name>\r\n"
00118     "vol\r\n"
00119     "ren   <org_file_name> <new_file_name>\r\n"
00120     "copy  <file_name> <file_name>\r\n"
00121     "mkdir <dir_name>\r\n"
00122     "cd    <dir_name>\r\n"
00123     "x     extend commands mode\r\n"
00124     "q     Return to main\r\n"
00125     "t     Show current time or Adjust time\r\n"
00126     "      e.g. t 18 3 28 14 48 20 -> 2018-03-28 14:48:20\r\n"
00127     "?     Help/You know the command\r\n"
00128     "\r\n";
00129 
00130 static const char HelpMsg1[] =
00131     "[File system controls]\r\n"
00132     " fi <ld#> [<mount>]- Force initialized the volume\r\n"
00133     " fs [<path>] - Show volume status\r\n"
00134     " fl [<path>] - Show a directory\r\n"
00135     " fo <mode> <file> - Open a file\r\n"
00136     "    <mode>  Read=1, Write=2\r\n"
00137     " fc - Close the file\r\n"
00138     " fe <ofs> - Move fp in normal seek\r\n"
00139     " fd <len> - Read and dump the file\r\n"
00140     " fr <len> - Read the file\r\n"
00141     " fw <len> <val> - Write to the file\r\n"
00142     " fn <org.name> <new.name> - Rename an object\r\n"
00143     " fu <name> - Unlink an object\r\n"
00144     " fv - Truncate the file at current fp\r\n"
00145     " fk <name> - Create a directory\r\n"
00146     " fa <atrr> <mask> <object name> - Change attribute of an object\r\n"
00147     " ft <year> <month> <day> <hour> <min> <sec> <name>"
00148     " - Change timestamp of an object\r\n"
00149     " fx <src.file> <dst.file> - Copy a file\r\n"
00150     " fg <path> - Change current directory\r\n"
00151     " fq - Show current directory\r\n"
00152     " fb <name> - Set volume label\r\n"
00153     " fm <ld#> <type> <csize> - Create file system\r\n"
00154     " fz [<len>] - Change/Show R/W length for fr/fw/fx command\r\n"
00155     "[Disk contorls]\r\n"
00156     " di <pd#> - Initialize disk\r\n"
00157     " dd [<pd#> <lba>] - Dump a secrtor\r\n"
00158     " ds <pd#> - Show disk status\r\n"
00159     "[Buffer controls]\r\n"
00160     " bd <ofs> - Dump working buffer\r\n"
00161     " be <ofs> [<data>] ... - Edit working buffer\r\n"
00162     " br <pd#> <lba> [<count>] - Read disk into working buffer\r\n"
00163     " bw <pd#> <lba> [<count>] - Write working buffer into disk\r\n"
00164     " bf <val> - Fill working buffer\r\n"
00165     "[Misc commands]\r\n"
00166     " q Return\r\n"
00167     " ? Help\r\n"
00168     "\r\n";
00169 
00170 //  Function prototypes --------------------------------------------------------
00171 #if (MBED_MAJOR_VERSION == 2)
00172 extern SDFileSystem fs;
00173 #elif (MBED_MAJOR_VERSION == 5)
00174 extern HeapBlockDevice bd;
00175 extern FATFileSystem fs;
00176 #endif
00177 
00178 static void extended_mon( char *ptr );
00179 static void v_next( char *ptr );
00180 static void d_next( char *ptr );
00181 static void c_next( char *ptr );
00182 static void m_next( char *ptr );
00183 static void r_next( char *ptr );
00184 static void t_next( char *ptr );
00185 static void memory_inf(char *ptr);
00186 static void disk_inf(char *ptr);
00187 
00188 static void crlf( void );
00189 static FRESULT scan_files( char* path );
00190 static void put_rc( FRESULT rc );
00191 static void file_inf( char *ptr );
00192 static void put_dump( void* buff, unsigned long addr, int len, int width );
00193 static void chk_and_set_time(char *ptr);
00194 static int xatoi ( char **str, long *res );
00195 
00196 void get_line (char *buff, int len);
00197 
00198 //  Object ---------------------------------------------------------------------
00199 extern  Serial pc;
00200 Timer   t;
00201 
00202 //------------------------------------------------------------------------------
00203 //  Control Program
00204 //------------------------------------------------------------------------------
00205 // Monitor program for File control
00206 void mon ()
00207 {
00208     char *ptr;
00209 
00210     Dirx = new FATFS_DIR;
00211     /* Open Uart to communicate with Host PC */
00212     PUTS(monmsg0);
00213     PUTS(monmsg1);
00214     crlf();
00215 #if FF_USE_LFN
00216     // no needs because FILINFO structure is changed
00217     Finfo.lfname = Lfname;
00218     Finfo.lfsize = sizeof Lfname;
00219 #endif
00220     for (;;) {
00221         DEBUG_LINE
00222         PUTC('>');
00223         ptr = Linebuf;
00224         get_line( ptr, sizeof(Linebuf) );
00225         switch ( *ptr++ ) {
00226                 // vol
00227             case 'v' :
00228                 v_next(ptr);
00229                 break;
00230                 // dir
00231             case 'd' :
00232                 d_next(ptr);
00233                 break;
00234                 // cd, copy
00235             case 'c' :
00236                 c_next(ptr);
00237                 break;
00238                 // mkdir
00239             case 'm' :
00240                 m_next(ptr);
00241                 break;
00242                 // ren
00243             case 'r' :
00244                 r_next(ptr);
00245                 break;
00246             case 't' :
00247                 t_next(ptr);
00248                 break;
00249             case 'x' :
00250                 extended_mon(ptr);
00251                 break;
00252                 // Help
00253             case '?' :
00254                 PUTS(HelpMsg0);
00255                 break;
00256                 // Exit monitor (return to main())
00257             case 'q' :
00258                 PUTS("Return to main\r\n");
00259                 return;
00260                 // Not a command
00261             default:
00262                 PUTS("? [HELP]=?");
00263                 crlf();
00264                 break;
00265         }
00266     }
00267 }
00268 
00269 uint32_t get_disk_freespace(void)
00270 {
00271     long  p1;
00272     UINT   s1, s2;
00273     FATFS  *fs;
00274     BYTE res;
00275 
00276     if (Dirx == NULL){
00277         Dirx = new FATFS_DIR;
00278     }
00279     char p = NULL;
00280     res = f_opendir(Dirx, &p);
00281     if (res) {
00282         return 0;
00283     }
00284     p1 = s1 = s2 = 0;
00285     for(;;) {
00286         res = f_readdir(Dirx, &Finfo);
00287         if ((res != FR_OK) || !Finfo.fname[0]) break;
00288         if (Finfo.fattrib & AM_DIR) {
00289             s2++;
00290         } else {
00291             s1++;
00292             p1 += Finfo.fsize;
00293         }
00294     }
00295     res = f_getfree(&p, (DWORD*)&p1, &fs);
00296     uint32_t size = p1 * fs->csize * 512;
00297     if (res == FR_OK) {
00298         return size;
00299     } else {
00300         return 0;
00301     }
00302 }
00303 
00304 static void extended_mon( char *ptr )
00305 {
00306     PUTS(HelpMsg1);
00307     while(true) {
00308         PUTS("e>");
00309         ptr = Linebuf;
00310         get_line( ptr, sizeof(Linebuf) );
00311         switch ( *ptr++ ) {
00312             case 'f' :
00313                 DEBUG_LINE;
00314                 file_inf(ptr);
00315                 break;
00316             case 'd' :
00317                 DEBUG_LINE;
00318                 disk_inf(ptr);
00319                 break;
00320             case 'm' :
00321                 DEBUG_LINE;
00322                 memory_inf(ptr);
00323                 break;
00324             case '?' :
00325                 DEBUG_LINE;
00326                 PUTS(HelpMsg1);
00327                 break;
00328             case 'q' :
00329                 DEBUG_LINE;
00330                 return;
00331             default:
00332                 PUTS( "?\r\n" );
00333         }
00334     }
00335 }
00336 
00337 //------------------------------------------------------------------------------
00338 // General monitor functions
00339 static void v_next( char *ptr )
00340 {
00341     switch ( *ptr++ ) {
00342         case 'o' :
00343             if (*ptr == 'l') {
00344                 *ptr = 's';
00345                 file_inf(ptr);  // fs [<path>] - Show volume status
00346             }
00347             break;
00348         default:
00349             PUTS( "?\r\n" );
00350     }
00351 }
00352 
00353 static void d_next(char *ptr)
00354 {
00355     switch ( *ptr++ ) {
00356         case 'i' :
00357             if (*ptr == 'r') {
00358                 *ptr = 'l';
00359                 file_inf(ptr);  // fl [<path>] - Directory listing
00360             }
00361             break;
00362         default:
00363             PUTS( "?\r\n" );
00364     }
00365 }
00366 
00367 static void c_next(char *ptr)
00368 {
00369     switch ( *ptr++ ) {
00370         case 'o' :
00371             if ((*ptr == 'p') && (*(ptr + 1) == 'y')) {
00372                 ptr++;
00373                 *ptr = 'x';
00374                 file_inf(ptr);  // fx <src_name> <dst_name> - Copy file
00375             }
00376             break;
00377         case 'd' :
00378             *ptr = 'g';
00379             file_inf(ptr);  // fx <src_name> <dst_name> - Copy file
00380             break;
00381         default:
00382             PUTS( "?\r\n" );
00383     }
00384 }
00385 
00386 static void m_next(char *ptr)
00387 {
00388     switch ( *ptr++ ) {
00389         case 'k' :
00390             if ((*ptr == 'd') && (*(ptr + 1) == 'i') && (*(ptr + 2) == 'r')) {
00391                 ptr += 2;
00392                 *ptr = 'k';
00393                 file_inf(ptr);  // fk <name> - Create a directory
00394             }
00395             break;
00396         default:
00397             PUTS("?\r\n");
00398     }
00399 }
00400 
00401 static void r_next(char *ptr)
00402 {
00403     switch (*ptr++) {
00404         case 'e' :
00405             if (*ptr == 'n') {
00406                 // fn <old_name> <new_name> - Change file/dir name
00407                 file_inf(ptr);
00408             }
00409             break;
00410         default:
00411             PUTS("?\r\n");
00412     }
00413 }
00414 
00415 static void t_next(char *ptr)
00416 {
00417     switch (*ptr++) {
00418         case ' ' :
00419         case 0x0d:
00420             chk_and_set_time(ptr);
00421         case 'y' :
00422             if ((*ptr == 'p') && (*(ptr + 1) == 'e')) {
00423                 ptr++;
00424                 *ptr = '&';
00425                 file_inf(ptr);
00426             }
00427             break;
00428         default:
00429             PUTS("?\r\n");
00430     }
00431 }
00432 
00433 static FRESULT scan_files (
00434     char* path      /* Pointer to the path name working buffer */
00435 )
00436 {
00437     FATFS_DIR  dirs;
00438     FRESULT res;
00439     BYTE i;
00440     char *fn;
00441 
00442     if ((res = f_opendir(&dirs, path)) == FR_OK) {
00443         i = strlen(path);
00444         PRINTF("path: %s, n=%u\r\n", path, i);
00445         while (((res = f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) {
00446             if (FF_FS_RPATH && Finfo.fname[0] == '.') {
00447                 continue;
00448             }
00449 #if FF_USE_LFN
00450             //fn = *Finfo.lfname ? Finfo.lfname : Finfo.fname;
00451             if (Finfo.altname[0] == 0) {
00452                 fn = Finfo.fname;
00453             } else {
00454                 fn = Finfo.altname;
00455             }
00456 #else
00457             fn = Finfo.fname;
00458 #endif
00459             if (Finfo.fattrib & AM_DIR) {
00460                 AccDirs++;
00461                 *(path+i) = '/';
00462                 strcpy(path+i+1, fn);
00463                 res = scan_files(path);
00464                 *(path+i) = '\0';
00465                 if (res != FR_OK) break;
00466             } else {
00467                 PRINTF("%s/%s\r\n", path, fn);
00468                 AccFiles++;
00469                 AccSize += Finfo.fsize;
00470             }
00471         }
00472     }
00473     return res;
00474 }
00475 
00476 static void put_rc (FRESULT rc)
00477 {
00478     const char *str =
00479         "OK\0" "DISK_ERR\0" "INT_ERR\0" "NOT_READY\0" "NO_FILE\0" "NO_PATH\0"
00480         "INVALID_NAME\0" "DENIED\0" "EXIST\0" "INVALID_OBJECT\0"
00481         "WRITE_PROTECTED\0" "INVALID_DRIVE\0" "NOT_ENABLED\0"
00482         "NO_FILE_SYSTEM\0" "MKFS_ABORTED\0" "TIMEOUT\0"
00483         "LOCKED\0" "NOT_ENOUGH_CORE\0" "TOO_MANY_OPEN_FILES\0";
00484     int i;
00485 
00486     for ( i = 0; i != rc && *str; i++ ) {
00487         while ( *str++ ) {
00488             ;
00489         }
00490     }
00491     PRINTF( "rc=%u FR_%s\r\n", (UINT)rc, str );
00492 }
00493 
00494 static void file_inf(char *ptr)
00495 {
00496     long  p1, p2, p3;
00497     CHAR   *ptr2;
00498     BYTE   f_res;
00499     UINT   s1, s2, cnt, blen = sizeof Buff;
00500     FATFS  *fs;
00501     static const BYTE ft[] = {0, 12, 16, 32};
00502     BYTE res;
00503     DWORD ofs = 0;
00504     uint32_t tim;
00505 
00506     switch (*ptr++) {
00507         case '&' :
00508             DEBUG_LINE;
00509             while (*ptr == ' ') ptr++;
00510             /* Open a file */
00511             f_res = f_open(&File1, ptr, FA_READ);
00512             if ( f_res ) {
00513                 put_rc((FRESULT)f_res);
00514                 break;
00515             }
00516             DEBUG_LINE;
00517             /* Read all lines and display it */
00518             while(true) {
00519                 f_res = f_read(&File1, (TCHAR*)Buff, blen, &cnt);
00520                 if ( f_res ) {
00521                     put_rc((FRESULT)f_res);
00522                     break;
00523                 }
00524                 for (s1 = 0; s1 < cnt; s1++) {
00525                     PUTC(Buff[s1]);
00526                 }
00527                 if (cnt != blen) {
00528                     break;
00529                 }
00530             }
00531             DEBUG_LINE;
00532             /* Close the file */
00533             f_close(&File1);
00534             break;
00535 
00536         case 'i' :  /* fi [<opt>]- Initialize logical drive */
00537             if ( !xatoi(&ptr, &p1) ) {
00538                 break;
00539             }
00540             if (!xatoi(&ptr, &p2)) p2 = 0;
00541             put_rc(f_mount(&Fatfs[p1], (const TCHAR*)p1, 0));
00542             break;
00543 
00544         case 's' :  /* fs [<path>] - Show volume status */
00545             f_res = f_getfree( ptr, (DWORD*)&p2, &fs );
00546             if ( f_res ) {
00547                 put_rc((FRESULT)f_res);
00548                 break;
00549             }
00550             PRINTF
00551             (
00552                 "\rFAT type = FAT%u\r\nBytes/Cluster"
00553                 " = %lu\r\nNumber of FATs = %u\r\n"
00554                 "Root DIR entries = %u\r\n"
00555                 "Sectors/FAT = %lu\r\n"
00556                 "Number of clusters = %lu\r\n"
00557                 "FAT start (lba) = %lu\r\n"
00558                 "DIR start (lba,clustor) = %lu\r\n"
00559                 "Data start (lba) = %lu\r\n",
00560                 ft[fs->fs_type & 3], (DWORD)fs->csize * 512, fs->n_fats,
00561                 fs->n_rootdir, fs->fsize, (DWORD)fs->n_fatent - 2,
00562                 fs->fatbase, fs->dirbase, fs->database
00563             );
00564             AccSize = AccFiles = AccDirs = 0;
00565             break;
00566         case 'l' :  /* fl [<path>] - Directory listing */
00567             while (*ptr == ' ') ptr++;
00568             res = f_opendir(Dirx, ptr);
00569             if (res) {
00570                 put_rc((FRESULT)res);
00571                 break;
00572             }
00573             p1 = s1 = s2 = 0;
00574             for(;;) {
00575                 res = f_readdir(Dirx, &Finfo);
00576                 if ((res != FR_OK) || !Finfo.fname[0]) break;
00577                 if (Finfo.fattrib & AM_DIR) {
00578                     s2++;
00579                 } else {
00580                     s1++;
00581                     p1 += Finfo.fsize;
00582                 }
00583                 PRINTF("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu  %s\r\n",
00584                        (Finfo.fattrib & AM_DIR) ? 'D' : '-',
00585                        (Finfo.fattrib & AM_RDO) ? 'R' : '-',
00586                        (Finfo.fattrib & AM_HID) ? 'H' : '-',
00587                        (Finfo.fattrib & AM_SYS) ? 'S' : '-',
00588                        (Finfo.fattrib & AM_ARC) ? 'A' : '-',
00589                        (Finfo.fdate >> 9) + 1980, (Finfo.fdate >> 5) & 15,
00590                        Finfo.fdate & 31,
00591                        (Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63,
00592                        Finfo.fsize, Finfo.fname);
00593             }
00594 #if 0   // f_getfree cannnot count under Dir, subdirectory area
00595             PRINTF("%4u File(s),%10lu bytes total\r\n%4u Dir(s)", s1, p1, s2);
00596             res = f_getfree(ptr, (DWORD*)&p1, &fs);
00597             if (res == FR_OK)
00598                 PRINTF(", %10lu bytes free\r\n", p1 * fs->csize * 512);
00599             else
00600                 put_rc((FRESULT)res);
00601 #else
00602             PRINTF("%4u File(s) = %10lu bytes total, %4u Dir(s)\r\n",
00603                    s1, p1, s2);
00604 #endif
00605             break;
00606 
00607         case 'o' :  /* fo <mode> <file> - Open a file */
00608             if (!xatoi(&ptr, &p1)) break;
00609             while (*ptr == ' ') ptr++;
00610             put_rc(f_open(&File1, ptr, (BYTE)p1));
00611 #if 0
00612             put_rc(f_open(&File1, "savedata.txt", 1));
00613             PRINTF("Open savedata.txt as read mode\r\n");
00614 #endif
00615             break;
00616 
00617         case 'c' :  /* fc - Close a file */
00618             put_rc(f_close(&File1));
00619             break;
00620 
00621         case 'e' :  /* fe - Seek file pointer */
00622             if (!xatoi(&ptr, &p1)) break;
00623             res = f_lseek(&File1, p1);
00624             put_rc((FRESULT)res);
00625             if (res == FR_OK)
00626                 PRINTF("fptr=%lu(0x%lX)\r\n", File1.fptr, File1.fptr);
00627             break;
00628 
00629         case 'd' :  /* fd <len> - read and dump file from current fp */
00630             if (!xatoi(&ptr, &p1)) break;
00631             ofs = File1.fptr;
00632             while (p1) {
00633                 if ((UINT)p1 >= 16) {
00634                     cnt = 16;
00635                     p1 -= 16;
00636                 } else                {
00637                     cnt = p1;
00638                     p1 = 0;
00639                 }
00640                 res = f_read(&File1, Buff, cnt, &cnt);
00641                 if (res != FR_OK) {
00642                     put_rc((FRESULT)res);
00643                     break;
00644                 }
00645                 if (!cnt) break;
00646                 put_dump(Buff, ofs, cnt, DW_CHAR);
00647                 ofs += 16;
00648             }
00649             break;
00650 
00651         case 'r' :  /* fr <len> - read file */
00652             if (!xatoi(&ptr, &p1)) break;
00653             p2 = 0;
00654             t.reset();
00655             t.start();
00656             while (p1) {
00657                 if ((UINT)p1 >= blen) {
00658                     cnt = blen;
00659                     p1 -= blen;
00660                 } else {
00661                     cnt = p1;
00662                     p1 = 0;
00663                 }
00664                 res = f_read(&File1, Buff, cnt, &s2);
00665                 if (res != FR_OK) {
00666                     put_rc((FRESULT)res);
00667                     break;
00668                 }
00669                 p2 += s2;
00670                 if (cnt != s2) break;
00671             }
00672             tim = t.read_ms();
00673             PRINTF("%lu bytes read with %lu kB/sec.\r\n",
00674                    p2, tim ? (p2 / tim) : 0);
00675             break;
00676 
00677         case 'w' :  /* fw <len> <val> - write file */
00678             if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break;
00679             memset(Buff, (BYTE)p2, blen);
00680             p2 = 0;
00681             t.reset();
00682             t.start();
00683             while (p1) {
00684                 if ((UINT)p1 >= blen) {
00685                     cnt = blen;
00686                     p1 -= blen;
00687                 } else {
00688                     cnt = p1;
00689                     p1 = 0;
00690                 }
00691                 res = f_write(&File1, Buff, cnt, &s2);
00692                 if (res != FR_OK) {
00693                     put_rc((FRESULT)res);
00694                     break;
00695                 }
00696                 p2 += s2;
00697                 if (cnt != s2) break;
00698             }
00699             tim = t.read_ms();
00700             PRINTF("%lu bytes written with %lu kB/sec.\r\n",
00701                    p2, tim ? (p2 / tim) : 0);
00702             break;
00703 
00704         case 'n' :  /* fn <org.name> <new.name> - Change name of an object */
00705             while (*ptr == ' ') ptr++;
00706             ptr2 = strchr(ptr, ' ');
00707             if (!ptr2) break;
00708             *ptr2++ = 0;
00709             while (*ptr2 == ' ') ptr2++;
00710             put_rc(f_rename(ptr, ptr2));
00711             break;
00712 
00713         case 'u' :  /* fu <name> - Unlink an object */
00714             while (*ptr == ' ') ptr++;
00715             put_rc(f_unlink(ptr));
00716             break;
00717 
00718         case 'v' :  /* fv - Truncate file */
00719             put_rc(f_truncate(&File1));
00720             break;
00721 
00722         case 'k' :  /* fk <name> - Create a directory */
00723             while (*ptr == ' ') ptr++;
00724             put_rc(f_mkdir(ptr));
00725             break;
00726 #if 0
00727         case 'a' :  /* fa <atrr> <mask> <name> - Change attribute of an object */
00728             if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break;
00729             while (*ptr == ' ') ptr++;
00730             put_rc(f_chmod(ptr, p1, p2));
00731             break;
00732 #endif
00733 #if 0
00734             /* ft <year> <month> <day> <hour> <min> <sec> <name>
00735                                                  - Change timestamp of an object */
00736         case 't' :
00737             if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) {
00738                 break;
00739             }
00740             Finfo.fdate = ((p1 - 1980) << 9) | ((p2 & 15) << 5) | (p3 & 31);
00741             if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) {
00742                 break;
00743             }
00744             Finfo.ftime =
00745                 ((p1 & 31) << 11) | ((p2 & 63) << 5) | ((p3 >> 1) & 31);
00746             put_rc(f_utime(ptr, &Finfo));
00747             break;
00748 #endif
00749 #if FILCPY_NOTUSE == 0
00750         case 'x' : /* fx <src_name> <dst_name> - Copy file */
00751             while ( *ptr == ' ' ) {
00752                 ptr++;
00753             }
00754             ptr2 = strchr( ptr, ' ' );
00755             if ( !ptr2 ) {
00756                 break;
00757             }
00758             *ptr2++ = 0;
00759             while ( *ptr2 == ' ' ) {
00760                 ptr2++;
00761             }
00762             f_res = f_open( &File1, ptr, FA_OPEN_EXISTING | FA_READ );
00763             PRINTF("Opening %s \r\n", ptr);
00764             if ( f_res ) {
00765                 put_rc( (FRESULT)f_res );
00766                 break;
00767             }
00768             f_res = f_open( &File2, ptr2, FA_CREATE_ALWAYS | FA_WRITE );
00769             PRINTF(" Creating %s \r\n", ptr2);
00770             if ( f_res ) {
00771                 put_rc( (FRESULT)f_res );
00772                 f_close( &File1 );
00773                 break;
00774             }
00775             PRINTF("Copying file...");
00776             p1 = 0;
00777             for ( ;; ) {
00778                 f_res = f_read( &File1, Buff, blen, &s1 );
00779                 if ( f_res || s1 == 0 ) {
00780                     break;   /* error or eof */
00781                 }
00782                 f_res = f_write( &File2, Buff, s1, &s2 );
00783                 p1 += s2;
00784                 if ( f_res || s2 < s1 ) {
00785                     break;   /* error or disk full */
00786                 }
00787             }
00788             f_close( &File1 );
00789             f_close( &File2 );
00790             crlf();
00791             break;
00792 #endif
00793 #if 0
00794         case 'x' : /* fx <src.name> <dst.name> - Copy a file */
00795             while (*ptr == ' ') ptr++;
00796             ptr2 = strchr(ptr, ' ');
00797             if (!ptr2) break;
00798             *ptr2++ = 0;
00799             while (*ptr2 == ' ') ptr2++;
00800             PRINTF("Opening \"%s\"", ptr);
00801             res = f_open(&File1, ptr, FA_OPEN_EXISTING | FA_READ);
00802             PUTS("\r\n");
00803             if (res) {
00804                 put_rc((FRESULT)res);
00805                 break;
00806             }
00807             PRINTF("Creating \"%s\"", ptr2);
00808             res = f_open(&File1, ptr2, FA_CREATE_ALWAYS | FA_WRITE);
00809             PUTS("\r\n");
00810             if (res) {
00811                 put_rc((FRESULT)res);
00812                 f_close(&File1);
00813                 break;
00814             }
00815             PRINTF("Copying file...");
00816             t.reset();
00817             t.start();
00818             p1 = 0;
00819             for (;;) {
00820                 res = f_read(&File1, Buff, blen, &s1);
00821                 if (res || s1 == 0) break;   /* error or eof */
00822                 res = f_write(&File2, Buff, s1, &s2);
00823                 p1 += s2;
00824                 if (res || s2 < s1) break;   /* error or disk full */
00825             }
00826             tim = t.read_ms();
00827             PRINTF("\r\n%lu bytes copied with %lu kB/sec.\r\n",
00828                    p1, tim ? (p1 / tim) : 0);
00829             f_close(&File1);
00830             f_close(&File2);
00831             break;
00832 #endif
00833 #if FF_FS_RPATH
00834         case 'g' :  /* fg <path> - Change current directory */
00835             while (*ptr == ' ') ptr++;
00836             put_rc(f_chdir(ptr));
00837             break;
00838 #if FF_FS_RPATH >= 2
00839         case 'q' :  /* fq - Show current dir path */
00840             res = f_getcwd(Linebuf, sizeof Linebuf);
00841             if (res)
00842                 put_rc(res);
00843             else
00844                 PRINTF("%s\r\n", Linebuf);
00845             break;
00846 #endif
00847 #endif
00848 #if FF_USE_LABEL
00849         case 'b' :  /* fb <name> - Set volume label */
00850             while (*ptr == ' ') ptr++;
00851             put_rc(f_setlabel(ptr));
00852             break;
00853 #endif  /* FF_USE_LABEL */
00854 #if FF_USE_MKFS
00855         case 'm' :  /* fm <type> <csize> - Create file system */
00856             if (!xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break;
00857             PRINTF("The volume will be formatted. Are you sure? (Y/n)=");
00858             get_line(Linebuf, sizeof Linebuf);
00859             if (Linebuf[0] == 'Y')
00860                 put_rc(f_mkfs("", (BYTE)p2, (DWORD)p3, Buff, sizeof Buff));
00861             break;
00862 #endif  /* FF_USE_MKFS */
00863             /* fz [<size>] - Change/Show R/W length for fr/fw/fx command */
00864         case 'z' :
00865             if (xatoi(&ptr, &p1) && p1 >= 1 && p1 <= (long)sizeof Buff)
00866                 blen = p1;
00867             PRINTF("blen=%u\r\n", blen);
00868             break;
00869     }
00870 }
00871 
00872 static void memory_inf(char *ptr)
00873 {
00874     long  p1, p2, p3;
00875 
00876     switch (*ptr++) {
00877         case 'd' :  /* md[b|h|w] <address> [<count>] - Dump memory */
00878             switch (*ptr++) {
00879                 case 'w':
00880                     p3 = DW_LONG;
00881                     break;
00882                 case 'h':
00883                     p3 = DW_SHORT;
00884                     break;
00885                 default:
00886                     p3 = DW_CHAR;
00887             }
00888             if (!xatoi(&ptr, &p1)) break;
00889             if (!xatoi(&ptr, &p2)) p2 = 128 / p3;
00890             for (ptr = (char*)p1; p2 >= 16 / p3; ptr += 16, p2 -= 16 / p3)
00891                 put_dump(ptr, (DWORD)ptr, 16 / p3, p3);
00892             if (p2) put_dump((BYTE*)ptr, (UINT)ptr, p2, p3);
00893             break;
00894         case 'f' :  /* mf <address> <value> <count> - Fill memory */
00895             if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) {
00896                 break;
00897             }
00898             while (p3--) {
00899                 *(BYTE*)p1 = (BYTE)p2;
00900                 p1++;
00901             }
00902             break;
00903         case 'e' :  /* me[b|h|w] <address> [<value> ...] - Edit memory */
00904             switch (*ptr++) {   /* Get data width */
00905                 case 'w':
00906                     p3 = DW_LONG;
00907                     break;
00908                 case 'h':
00909                     p3 = DW_SHORT;
00910                     break;
00911                 default:
00912                     p3 = DW_CHAR;
00913             }
00914             if (!xatoi(&ptr, &p1)) break;   /* Get start address */
00915             if (xatoi(&ptr, &p2)) { /* 2nd parameter is given (direct mode) */
00916                 do {
00917                     switch (p3) {
00918                         case DW_LONG:
00919                             *(DWORD*)p1 = (DWORD)p2;
00920                             break;
00921                         case DW_SHORT:
00922                             *(WORD*)p1 = (WORD)p2;
00923                             break;
00924                         default:
00925                             *(BYTE*)p1 = (BYTE)p2;
00926                     }
00927                     p1 += p3;
00928                 } while (xatoi(&ptr, &p2)); /* Get next value */
00929                 break;
00930             }
00931             for (;;) {  /* 2nd parameter is not given (interactive mode) */
00932                 switch (p3) {
00933                     case DW_LONG:
00934                         PRINTF("%08X 0x%08X-", p1, *(DWORD*)p1);
00935                         break;
00936                     case DW_SHORT:
00937                         PRINTF("%08X 0x%04X-", p1, *(WORD*)p1);
00938                         break;
00939                     default:
00940                         PRINTF("%08X 0x%02X-", p1, *(BYTE*)p1);
00941                 }
00942                 ptr = Linebuf;
00943                 get_line(ptr, sizeof Linebuf);
00944                 if (*ptr == '.') break;
00945                 if ((BYTE)*ptr >= ' ') {
00946                     if (!xatoi(&ptr, &p2)) continue;
00947                     switch (p3) {
00948                         case DW_LONG:
00949                             *(DWORD*)p1 = (DWORD)p2;
00950                             break;
00951                         case DW_SHORT:
00952                             *(WORD*)p1 = (WORD)p2;
00953                             break;
00954                         default:
00955                             *(BYTE*)p1 = (BYTE)p2;
00956                     }
00957                 }
00958                 p1 += p3;
00959             }
00960     }
00961 }
00962 
00963 static void disk_inf(char *ptr)
00964 {
00965     long  p1, p2;
00966     UINT   s1;
00967     BYTE res, b, drv = 0;
00968     DWORD ofs = 0, sect = 0, blk[2];
00969 
00970     switch (*ptr++) {
00971         case 'd' :  /* dd [<pd#> <sect>] - Dump secrtor */
00972             if (!xatoi(&ptr, &p1)) {
00973                 p1 = drv;
00974                 p2 = sect;
00975             } else {
00976                 if (!xatoi(&ptr, &p2)) break;
00977             }
00978             drv = (BYTE)p1;
00979             sect = p2;
00980             res = disk_read(drv, Buff, sect, 1);
00981             if (res) {
00982                 PRINTF("rc=%d\r\n", (WORD)res);
00983                 break;
00984             }
00985             PRINTF("PD#:%u LBA:%lu\r\n", drv, sect++);
00986             for (ptr=(char*)Buff, ofs = 0; ofs < 0x200; ptr += 16, ofs += 16)
00987                 put_dump((BYTE*)ptr, ofs, 16, DW_CHAR);
00988             break;
00989 
00990         case 'i' :  /* di <pd#> - Initialize disk */
00991             if (!xatoi(&ptr, &p1)) break;
00992             PRINTF("rc=%d\r\n", (WORD)disk_initialize((BYTE)p1));
00993             break;
00994 
00995         case 's' :  /* ds <pd#> - Show disk status */
00996             if (!xatoi(&ptr, &p1)) break;
00997             if (disk_ioctl((BYTE)p1, GET_SECTOR_COUNT, &p2) == RES_OK) {
00998                 PRINTF("Drive size: %lu sectors\r\n", p2);
00999             }
01000             if (disk_ioctl((BYTE)p1, GET_BLOCK_SIZE, &p2) == RES_OK) {
01001                 PRINTF("Block size: %lu sectors\r\n", p2);
01002             }
01003             if (disk_ioctl((BYTE)p1, MMC_GET_TYPE, &b) == RES_OK) {
01004                 PRINTF("Media type: %u\r\n", b);
01005             }
01006             if (disk_ioctl((BYTE)p1, MMC_GET_CSD, Buff) == RES_OK) {
01007                 PUTS("CSD:\r\n");
01008                 put_dump(Buff, 0, 16, DW_CHAR);
01009             }
01010             if (disk_ioctl((BYTE)p1, MMC_GET_CID, Buff) == RES_OK) {
01011                 PUTS("CID:\r\n");
01012                 put_dump(Buff, 0, 16, DW_CHAR);
01013             }
01014             if (disk_ioctl((BYTE)p1, MMC_GET_OCR, Buff) == RES_OK) {
01015                 PUTS("OCR:\r\n");
01016                 put_dump(Buff, 0, 4, DW_CHAR);
01017             }
01018             if (disk_ioctl((BYTE)p1, MMC_GET_SDSTAT, Buff) == RES_OK) {
01019                 PUTS("SD Status:\r\n");
01020                 for (s1 = 0; s1 < 64; s1 += 16) {
01021                     put_dump(Buff+s1, s1, 16, DW_CHAR);
01022                 }
01023             }
01024             break;
01025 
01026         case 'c' :  /* Disk ioctl */
01027             switch (*ptr++) {
01028                 case 's' :  /* dcs <pd#> - CTRL_SYNC */
01029                     if (!xatoi(&ptr, &p1)) break;
01030                     PRINTF("rc=%d\r\n", disk_ioctl((BYTE)p1, CTRL_SYNC, 0));
01031                     break;
01032                 case 'e' :  /* dce <pd#> <s.lba> <e.lba> - CTRL_TRIM */
01033                     if (!xatoi(&ptr, &p1) ||
01034                             !xatoi(&ptr, (long*)&blk[0]) ||
01035                             !xatoi(&ptr, (long*)&blk[1])) {
01036                         break;
01037                     }
01038                     PRINTF("rc=%d\r\n", disk_ioctl((BYTE)p1, CTRL_TRIM, blk));
01039                     break;
01040             }
01041     }
01042 }
01043 
01044 void put_dump (
01045     void* buff,             /* Pointer to the array to be dumped */
01046     unsigned long addr,     /* Heading address value */
01047     int len,                /* Number of items to be dumped */
01048     int width               /* Size of the items (DW_CHAR, DW_SHORT, DW_LONG) */
01049 )
01050 {
01051     int i;
01052     unsigned char *bp;
01053     unsigned short *sp;
01054     unsigned long *lp;
01055 
01056     PRINTF( "%08lx ", addr );      /* address */
01057     switch ( width )  {
01058         case DW_CHAR:
01059             bp = (unsigned char *)buff;
01060             for ( i = 0; i < len; i++ ) {       /* Hexdecimal dump */
01061                 PRINTF( " %02x", bp[i] );
01062             }
01063             PUTC(' ');
01064             for ( i = 0; i < len; i++ ) {       /* ASCII dump */
01065                 PUTC( (bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.' );
01066             }
01067             break;
01068         case DW_SHORT:
01069             sp = (unsigned short *)buff;
01070             do {                            /* Hexdecimal dump */
01071                 PRINTF( " %04x", *sp++ );
01072             } while ( --len );
01073             break;
01074         case DW_LONG:
01075             lp = (unsigned long *)buff;
01076             do {                            /* Hexdecimal dump */
01077                 PRINTF( " %08lx", *lp++ );
01078             } while ( --len );
01079             break;
01080     }
01081     PUTS( "\r\n" );
01082 }
01083 
01084 // RTC related subroutines
01085 void chk_and_set_time(char *ptr)
01086 {
01087     char buf[64];
01088 
01089     long p1;
01090     struct tm t;
01091     time_t seconds;
01092 
01093     if (xatoi(&ptr, &p1)) {
01094         t.tm_year       = (uint8_t)p1 + 100;
01095         pc.printf("Year:%d ",p1);
01096         xatoi( &ptr, &p1 );
01097         t.tm_mon        = (uint8_t)p1 - 1;
01098         pc.printf("Month:%d ",p1);
01099         xatoi( &ptr, &p1 );
01100         t.tm_mday       = (uint8_t)p1;
01101         pc.printf("Day:%d ",p1);
01102         xatoi( &ptr, &p1 );
01103         t.tm_hour       = (uint8_t)p1;
01104         pc.printf("Hour:%d ",p1);
01105         xatoi( &ptr, &p1 );
01106         t.tm_min        = (uint8_t)p1;
01107         pc.printf("Min:%d ",p1);
01108         xatoi( &ptr, &p1 );
01109         t.tm_sec        = (uint8_t)p1;
01110         pc.printf("Sec: %d \r\n",p1);
01111         seconds = mktime(&t);
01112         set_time(seconds);
01113     } else {
01114         seconds = time(NULL);
01115     }
01116     strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
01117     pc.printf("[Time] %s", buf);
01118 }
01119 
01120 //  Get key input data
01121 void get_line (char *buff, int len)
01122 {
01123     char c;
01124     int idx = 0;
01125 
01126     for (;;) {
01127         c = GETC();
01128         //    Added by Kenji Arai / JH1PJL   May 9th, 2010
01129         if (c == '\r') {
01130             buff[idx++] = c;
01131             break;
01132         }
01133         if ((c == '\b') && idx) {
01134             idx--;
01135             PUTC(c);
01136             PUTC(' ');
01137             PUTC(c);
01138         }
01139         if (((uint8_t)c >= ' ') && (idx < len - 1)) {
01140             buff[idx++] = c;
01141             PUTC(c);
01142         }
01143     }
01144     buff[idx] = 0;
01145     PUTS("\r\n");
01146 }
01147 
01148 /*  Outpur LF & CR */
01149 void crlf( void )
01150 {
01151     PRINTF( "\r\n" );
01152 }
01153 
01154 /*  Check key input */
01155 unsigned int check_hit_key (void)
01156 {
01157     return ( READABLE() );
01158 }
01159 
01160 /*----------------------------------------------*/
01161 /* Get a value of the string                    */
01162 /*----------------------------------------------*/
01163 /*  "123 -5   0x3ff 0b1111 0377  w "
01164         ^                           1st call returns 123 and next ptr
01165            ^                        2nd call returns -5 and next ptr
01166                    ^                3rd call returns 1023 and next ptr
01167                           ^         4th call returns 15 and next ptr
01168                                ^    5th call returns 255 and next ptr
01169                                   ^ 6th call fails and returns 0
01170 */
01171 int xatoi (         /* 0:Failed, 1:Successful */
01172     char **str,     /* Pointer to pointer to the string */
01173     long *res       /* Pointer to the valiable to store the value */
01174 )
01175 {
01176     unsigned long val;
01177     unsigned char c, r, s = 0;
01178 
01179     *res = 0;
01180     while ( (c = **str) == ' ' ) {
01181         (*str)++;   /* Skip leading spaces */
01182     }
01183     if ( c == '-' ) {       /* negative? */
01184         s = 1;
01185         c = *(++(*str));
01186     }
01187     if ( c == '0' ) {
01188         c = *(++(*str));
01189         switch (c) {
01190             case 'x':       /* hexdecimal */
01191                 r = 16;
01192                 c = *(++(*str));
01193                 break;
01194             case 'b':       /* binary */
01195                 r = 2;
01196                 c = *(++(*str));
01197                 break;
01198             default:
01199                 if ( c <= ' ' ) return 1;   /* single zero */
01200                 if ( c < '0' || c > '9' ) return 0; /* invalid char */
01201                 r = 8;      /* octal */
01202         }
01203     } else {
01204         if ( c < '0' || c > '9' ) return 0; /* EOL or invalid char */
01205         r = 10;         /* decimal */
01206     }
01207     val = 0;
01208     while ( c > ' ' ) {
01209         if ( c >= 'a' ) {
01210             c -= 0x20;
01211         }
01212         c -= '0';
01213         if ( c >= 17 ) {
01214             c -= 7;
01215             if ( c <= 9 ) {
01216                 return 0;   /* invalid char */
01217             }
01218         }
01219         if ( c >= r ) {
01220             return 0;   /* invalid char for current radix */
01221         }
01222         val = val * r + c;
01223         c = *(++(*str));
01224     }
01225     if (s) val = 0 - val;           /* apply sign if needed */
01226     *res = val;
01227     return 1;
01228 }