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