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