function test USBMSD(as external strage for PC USB) and USBSerial. Switching between USBMSD and USBSerial(Not work simultaneously)

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