function test USBMSD(as external strage for PC USB) and USBSerial. Switching between USBMSD and USBSerial(Not work simultaneously)
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 }
Generated on Wed Jul 20 2022 09:50:42 by 1.7.2