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,'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 }
Generated on Mon Jul 18 2022 12:06:40 by
1.7.2