RAM Disk function using Mbed os5 standard library
Please refer following my Notebook page.
/users/kenjiArai/notebook/sd-card-control-new/#
FatFs_Mon/mon.cpp
- Committer:
- kenjiArai
- Date:
- 2018-04-07
- Revision:
- 0:308d4fafaafb
- Child:
- 1:58fc0cbd9a41
File content as of revision 0:308d4fafaafb:
/* * mbed Application program for the mbed * FatFs Check program / monitor part * * Copyright (c) 2015,'18 Kenji Arai / JH1PJL * http://www.page.sannet.ne.jp/kenjia/index.html * https://os.mbed.com/users/kenjiArai/ * Created: May 5th, 2015 * Revised: June 14th, 2015 * Revised: April 7th, 2018 */ /* *---------------- REFERENCE --------------------------------------------------- * Original Source Information * FatFs sample program * ChaN FatFs http://elm-chan.org/ * http://elm-chan.org/fsw/ff/00index_e.html */ /*----------------------------------------------------------------------*/ /* FAT file system sample project for FatFs (C)ChaN, 2016 */ /*----------------------------------------------------------------------*/ // Include -------------------------------------------------------------------- #include "mbed.h" #if (MBED_MAJOR_VERSION == 2) #include "SDFileSystem.h" #elif (MBED_MAJOR_VERSION == 5) #include "FATFileSystem.h" #endif #include "ff.h" #include "ffconf.h" #include "diskio.h" #include "mon.h" // Definition ----------------------------------------------------------------- #define DO_DEBUG 0 #if DO_DEBUG #define DEBUG_LINE pc.printf("line:%d\r\n", __LINE__); #else #define DEBUG_LINE {;} #endif // Com #if 1 #define BAUD(x) pc.baud(x) #define GETC(x) pc.getc(x) #define PUTC(x) pc.putc(x) #define PUTS(x) pc.puts(x) #define PRINTF(...) pc.printf(__VA_ARGS__) #define READABLE(x) pc.readable(x) #else #define BAUD(x) {;} #define GETC(x) {;} #define PUTC(x) {;} #define PRINTF(...) {;} #define READABLE(x) {;} #endif #define UTC_JST_OFFSET (32400) // +9 hours // from ffconf.h #define _VOLUMES 1 #define FF_USE_LFN 0 #if !defined(FF_FS_RPATH) #define FF_FS_RPATH 0 #endif #define DW_CHAR sizeof(char) #define DW_SHORT sizeof(short) #define DW_LONG sizeof(long) /* These types must be 16-bit, 32-bit or larger integer */ typedef int INT; typedef unsigned int UINT; /* These types must be 8-bit integer */ typedef char CHAR; typedef unsigned char UCHAR; typedef unsigned char BYTE; /* These types must be 16-bit integer */ typedef short SHORT; typedef unsigned short USHORT; typedef unsigned short WORD; typedef unsigned short WCHAR; /* These types must be 32-bit integer */ typedef long LONG; typedef unsigned long ULONG; typedef unsigned long DWORD; /* by Kenji Arai / JH1PJL September 10th, 2012 */ typedef unsigned long long DDWORD; // RAM ------------------------------------------------------------------------ BYTE Buff[4096]; char Linebuf[128]; // Console input buffer FATFS Fatfs[_VOLUMES]; // File system object for each logical drive FIL File1, File2; // File objects FATFS_DIR* Dirx; FILINFO Finfo; #if FF_USE_LFN //inside of FILINFO char Lfname[512]; #endif DWORD AccSize; // Work register for fs command WORD AccFiles, AccDirs; // ROM / Constant data -------------------------------------------------------- char *const monmsg0 = "Start monitor program for FatFs File System\r\n"; char *const monmsg1 = " <Please press any key to start the monitor>"; static const char HelpMsg0[] = "dir <full_pass>\r\n" "type <file_name>\r\n" "vol\r\n" "ren <org_file_name> <new_file_name>\r\n" "copy <file_name> <file_name>\r\n" "mkdir <dir_name>\r\n" "cd <dir_name>\r\n" "x extend commands mode\r\n" "q Return to main\r\n" "t Show current time or Adjust time\r\n" " e.g. t 18 3 28 14 48 20 -> 2018-03-28 14:48:20\r\n" "? Help/You know the command\r\n" "\r\n"; static const char HelpMsg1[] = "[File system controls]\r\n" " fi <ld#> [<mount>]- Force initialized the volume\r\n" " fs [<path>] - Show volume status\r\n" " fl [<path>] - Show a directory\r\n" " fo <mode> <file> - Open a file\r\n" " <mode> Read=1, Write=2\r\n" " fc - Close the file\r\n" " fe <ofs> - Move fp in normal seek\r\n" " fd <len> - Read and dump the file\r\n" " fr <len> - Read the file\r\n" " fw <len> <val> - Write to the file\r\n" " fn <org.name> <new.name> - Rename an object\r\n" " fu <name> - Unlink an object\r\n" " fv - Truncate the file at current fp\r\n" " fk <name> - Create a directory\r\n" " fa <atrr> <mask> <object name> - Change attribute of an object\r\n" " ft <year> <month> <day> <hour> <min> <sec> <name>" " - Change timestamp of an object\r\n" " fx <src.file> <dst.file> - Copy a file\r\n" " fg <path> - Change current directory\r\n" " fq - Show current directory\r\n" " fb <name> - Set volume label\r\n" " fm <ld#> <type> <csize> - Create file system\r\n" " fz [<len>] - Change/Show R/W length for fr/fw/fx command\r\n" "[Disk contorls]\r\n" " di <pd#> - Initialize disk\r\n" " dd [<pd#> <lba>] - Dump a secrtor\r\n" " ds <pd#> - Show disk status\r\n" "[Buffer controls]\r\n" " bd <ofs> - Dump working buffer\r\n" " be <ofs> [<data>] ... - Edit working buffer\r\n" " br <pd#> <lba> [<count>] - Read disk into working buffer\r\n" " bw <pd#> <lba> [<count>] - Write working buffer into disk\r\n" " bf <val> - Fill working buffer\r\n" "[Misc commands]\r\n" " q Return\r\n" " ? Help\r\n" "\r\n"; // Function prototypes -------------------------------------------------------- #if (MBED_MAJOR_VERSION == 2) extern SDFileSystem fs; #elif (MBED_MAJOR_VERSION == 5) extern HeapBlockDevice bd; extern FATFileSystem fs; #endif static void extended_mon( char *ptr ); static void v_next( char *ptr ); static void d_next( char *ptr ); static void c_next( char *ptr ); static void m_next( char *ptr ); static void r_next( char *ptr ); static void t_next( char *ptr ); static void memory_inf(char *ptr); static void disk_inf(char *ptr); static void crlf( void ); static FRESULT scan_files( char* path ); static void put_rc( FRESULT rc ); static void file_inf( char *ptr ); static void put_dump( void* buff, unsigned long addr, int len, int width ); static void chk_and_set_time(char *ptr); static int xatoi ( char **str, long *res ); void get_line (char *buff, int len); // Object --------------------------------------------------------------------- extern Serial pc; Timer t; //------------------------------------------------------------------------------ // Control Program //------------------------------------------------------------------------------ // Monitor program for File control void mon () { char *ptr; Dirx = new FATFS_DIR; /* Open Uart to communicate with Host PC */ PUTS(monmsg0); PUTS(monmsg1); crlf(); #if FF_USE_LFN // no needs because FILINFO structure is changed Finfo.lfname = Lfname; Finfo.lfsize = sizeof Lfname; #endif for (;;) { DEBUG_LINE PUTC('>'); ptr = Linebuf; get_line( ptr, sizeof(Linebuf) ); switch ( *ptr++ ) { // vol case 'v' : v_next(ptr); break; // dir case 'd' : d_next(ptr); break; // cd, copy case 'c' : c_next(ptr); break; // mkdir case 'm' : m_next(ptr); break; // ren case 'r' : r_next(ptr); break; case 't' : t_next(ptr); break; case 'x' : extended_mon(ptr); break; // Help case '?' : PUTS(HelpMsg0); break; // Exit monitor (return to main()) case 'q' : PUTS("Return to main\r\n"); return; // Not a command default: PUTS("? [HELP]=?"); crlf(); break; } } } uint32_t get_disk_freespace(void) { long p1; UINT s1, s2; FATFS *fs; BYTE res; if (Dirx == NULL){ Dirx = new FATFS_DIR; } char p = NULL; res = f_opendir(Dirx, &p); if (res) { return 0; } p1 = s1 = s2 = 0; for(;;) { res = f_readdir(Dirx, &Finfo); if ((res != FR_OK) || !Finfo.fname[0]) break; if (Finfo.fattrib & AM_DIR) { s2++; } else { s1++; p1 += Finfo.fsize; } } res = f_getfree(&p, (DWORD*)&p1, &fs); uint32_t size = p1 * fs->csize * 512; if (res == FR_OK) { return size; } else { return 0; } } static void extended_mon( char *ptr ) { PUTS(HelpMsg1); while(true) { PUTS("e>"); ptr = Linebuf; get_line( ptr, sizeof(Linebuf) ); switch ( *ptr++ ) { case 'f' : DEBUG_LINE; file_inf(ptr); break; case 'd' : DEBUG_LINE; disk_inf(ptr); break; case 'm' : DEBUG_LINE; memory_inf(ptr); break; case '?' : DEBUG_LINE; PUTS(HelpMsg1); break; case 'q' : DEBUG_LINE; return; default: PUTS( "?\r\n" ); } } } //------------------------------------------------------------------------------ // General monitor functions static void v_next( char *ptr ) { switch ( *ptr++ ) { case 'o' : if (*ptr == 'l') { *ptr = 's'; file_inf(ptr); // fs [<path>] - Show volume status } break; default: PUTS( "?\r\n" ); } } static void d_next(char *ptr) { switch ( *ptr++ ) { case 'i' : if (*ptr == 'r') { *ptr = 'l'; file_inf(ptr); // fl [<path>] - Directory listing } break; default: PUTS( "?\r\n" ); } } static void c_next(char *ptr) { switch ( *ptr++ ) { case 'o' : if ((*ptr == 'p') && (*(ptr + 1) == 'y')) { ptr++; *ptr = 'x'; file_inf(ptr); // fx <src_name> <dst_name> - Copy file } break; case 'd' : *ptr = 'g'; file_inf(ptr); // fx <src_name> <dst_name> - Copy file break; default: PUTS( "?\r\n" ); } } static void m_next(char *ptr) { switch ( *ptr++ ) { case 'k' : if ((*ptr == 'd') && (*(ptr + 1) == 'i') && (*(ptr + 2) == 'r')) { ptr += 2; *ptr = 'k'; file_inf(ptr); // fk <name> - Create a directory } break; default: PUTS("?\r\n"); } } static void r_next(char *ptr) { switch (*ptr++) { case 'e' : if (*ptr == 'n') { // fn <old_name> <new_name> - Change file/dir name file_inf(ptr); } break; default: PUTS("?\r\n"); } } static void t_next(char *ptr) { switch (*ptr++) { case ' ' : case 0x0d: chk_and_set_time(ptr); case 'y' : if ((*ptr == 'p') && (*(ptr + 1) == 'e')) { ptr++; *ptr = '&'; file_inf(ptr); } break; default: PUTS("?\r\n"); } } static FRESULT scan_files ( char* path /* Pointer to the path name working buffer */ ) { FATFS_DIR dirs; FRESULT res; BYTE i; char *fn; if ((res = f_opendir(&dirs, path)) == FR_OK) { i = strlen(path); PRINTF("path: %s, n=%u\r\n", path, i); while (((res = f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) { if (FF_FS_RPATH && Finfo.fname[0] == '.') { continue; } #if FF_USE_LFN //fn = *Finfo.lfname ? Finfo.lfname : Finfo.fname; if (Finfo.altname[0] == 0) { fn = Finfo.fname; } else { fn = Finfo.altname; } #else fn = Finfo.fname; #endif if (Finfo.fattrib & AM_DIR) { AccDirs++; *(path+i) = '/'; strcpy(path+i+1, fn); res = scan_files(path); *(path+i) = '\0'; if (res != FR_OK) break; } else { PRINTF("%s/%s\r\n", path, fn); AccFiles++; AccSize += Finfo.fsize; } } } return res; } static void put_rc (FRESULT rc) { const char *str = "OK\0" "DISK_ERR\0" "INT_ERR\0" "NOT_READY\0" "NO_FILE\0" "NO_PATH\0" "INVALID_NAME\0" "DENIED\0" "EXIST\0" "INVALID_OBJECT\0" "WRITE_PROTECTED\0" "INVALID_DRIVE\0" "NOT_ENABLED\0" "NO_FILE_SYSTEM\0" "MKFS_ABORTED\0" "TIMEOUT\0" "LOCKED\0" "NOT_ENOUGH_CORE\0" "TOO_MANY_OPEN_FILES\0"; int i; for ( i = 0; i != rc && *str; i++ ) { while ( *str++ ) { ; } } PRINTF( "rc=%u FR_%s\r\n", (UINT)rc, str ); } static void file_inf(char *ptr) { long p1, p2, p3; CHAR *ptr2; BYTE f_res; UINT s1, s2, cnt, blen = sizeof Buff; FATFS *fs; static const BYTE ft[] = {0, 12, 16, 32}; BYTE res; DWORD ofs = 0; uint32_t tim; switch (*ptr++) { case '&' : DEBUG_LINE; while (*ptr == ' ') ptr++; /* Open a file */ f_res = f_open(&File1, ptr, FA_READ); if ( f_res ) { put_rc((FRESULT)f_res); break; } DEBUG_LINE; /* Read all lines and display it */ while(true) { f_res = f_read(&File1, (TCHAR*)Buff, blen, &cnt); if ( f_res ) { put_rc((FRESULT)f_res); break; } for (s1 = 0; s1 < cnt; s1++) { PUTC(Buff[s1]); } if (cnt != blen) { break; } } DEBUG_LINE; /* Close the file */ f_close(&File1); break; case 'i' : /* fi [<opt>]- Initialize logical drive */ if ( !xatoi(&ptr, &p1) ) { break; } if (!xatoi(&ptr, &p2)) p2 = 0; put_rc(f_mount(&Fatfs[p1], (const TCHAR*)p1, 0)); break; case 's' : /* fs [<path>] - Show volume status */ f_res = f_getfree( ptr, (DWORD*)&p2, &fs ); if ( f_res ) { put_rc((FRESULT)f_res); break; } PRINTF ( "\rFAT type = FAT%u\r\nBytes/Cluster" " = %lu\r\nNumber of FATs = %u\r\n" "Root DIR entries = %u\r\n" "Sectors/FAT = %lu\r\n" "Number of clusters = %lu\r\n" "FAT start (lba) = %lu\r\n" "DIR start (lba,clustor) = %lu\r\n" "Data start (lba) = %lu\r\n", ft[fs->fs_type & 3], (DWORD)fs->csize * 512, fs->n_fats, fs->n_rootdir, fs->fsize, (DWORD)fs->n_fatent - 2, fs->fatbase, fs->dirbase, fs->database ); AccSize = AccFiles = AccDirs = 0; break; case 'l' : /* fl [<path>] - Directory listing */ while (*ptr == ' ') ptr++; res = f_opendir(Dirx, ptr); if (res) { put_rc((FRESULT)res); break; } p1 = s1 = s2 = 0; for(;;) { res = f_readdir(Dirx, &Finfo); if ((res != FR_OK) || !Finfo.fname[0]) break; if (Finfo.fattrib & AM_DIR) { s2++; } else { s1++; p1 += Finfo.fsize; } PRINTF("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %s\r\n", (Finfo.fattrib & AM_DIR) ? 'D' : '-', (Finfo.fattrib & AM_RDO) ? 'R' : '-', (Finfo.fattrib & AM_HID) ? 'H' : '-', (Finfo.fattrib & AM_SYS) ? 'S' : '-', (Finfo.fattrib & AM_ARC) ? 'A' : '-', (Finfo.fdate >> 9) + 1980, (Finfo.fdate >> 5) & 15, Finfo.fdate & 31, (Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63, Finfo.fsize, Finfo.fname); } #if 0 // f_getfree cannnot count under Dir, subdirectory area PRINTF("%4u File(s),%10lu bytes total\r\n%4u Dir(s)", s1, p1, s2); res = f_getfree(ptr, (DWORD*)&p1, &fs); if (res == FR_OK) PRINTF(", %10lu bytes free\r\n", p1 * fs->csize * 512); else put_rc((FRESULT)res); #else PRINTF("%4u File(s) = %10lu bytes total, %4u Dir(s)\r\n", s1, p1, s2); #endif break; case 'o' : /* fo <mode> <file> - Open a file */ if (!xatoi(&ptr, &p1)) break; while (*ptr == ' ') ptr++; put_rc(f_open(&File1, ptr, (BYTE)p1)); #if 0 put_rc(f_open(&File1, "savedata.txt", 1)); PRINTF("Open savedata.txt as read mode\r\n"); #endif break; case 'c' : /* fc - Close a file */ put_rc(f_close(&File1)); break; case 'e' : /* fe - Seek file pointer */ if (!xatoi(&ptr, &p1)) break; res = f_lseek(&File1, p1); put_rc((FRESULT)res); if (res == FR_OK) PRINTF("fptr=%lu(0x%lX)\r\n", File1.fptr, File1.fptr); break; case 'd' : /* fd <len> - read and dump file from current fp */ if (!xatoi(&ptr, &p1)) break; ofs = File1.fptr; while (p1) { if ((UINT)p1 >= 16) { cnt = 16; p1 -= 16; } else { cnt = p1; p1 = 0; } res = f_read(&File1, Buff, cnt, &cnt); if (res != FR_OK) { put_rc((FRESULT)res); break; } if (!cnt) break; put_dump(Buff, ofs, cnt, DW_CHAR); ofs += 16; } break; case 'r' : /* fr <len> - read file */ if (!xatoi(&ptr, &p1)) break; p2 = 0; t.reset(); t.start(); while (p1) { if ((UINT)p1 >= blen) { cnt = blen; p1 -= blen; } else { cnt = p1; p1 = 0; } res = f_read(&File1, Buff, cnt, &s2); if (res != FR_OK) { put_rc((FRESULT)res); break; } p2 += s2; if (cnt != s2) break; } tim = t.read_ms(); PRINTF("%lu bytes read with %lu kB/sec.\r\n", p2, tim ? (p2 / tim) : 0); break; case 'w' : /* fw <len> <val> - write file */ if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break; memset(Buff, (BYTE)p2, blen); p2 = 0; t.reset(); t.start(); while (p1) { if ((UINT)p1 >= blen) { cnt = blen; p1 -= blen; } else { cnt = p1; p1 = 0; } res = f_write(&File1, Buff, cnt, &s2); if (res != FR_OK) { put_rc((FRESULT)res); break; } p2 += s2; if (cnt != s2) break; } tim = t.read_ms(); PRINTF("%lu bytes written with %lu kB/sec.\r\n", p2, tim ? (p2 / tim) : 0); break; case 'n' : /* fn <org.name> <new.name> - Change name of an object */ while (*ptr == ' ') ptr++; ptr2 = strchr(ptr, ' '); if (!ptr2) break; *ptr2++ = 0; while (*ptr2 == ' ') ptr2++; put_rc(f_rename(ptr, ptr2)); break; case 'u' : /* fu <name> - Unlink an object */ while (*ptr == ' ') ptr++; put_rc(f_unlink(ptr)); break; case 'v' : /* fv - Truncate file */ put_rc(f_truncate(&File1)); break; case 'k' : /* fk <name> - Create a directory */ while (*ptr == ' ') ptr++; put_rc(f_mkdir(ptr)); break; #if 0 case 'a' : /* fa <atrr> <mask> <name> - Change attribute of an object */ if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break; while (*ptr == ' ') ptr++; put_rc(f_chmod(ptr, p1, p2)); break; #endif #if 0 /* ft <year> <month> <day> <hour> <min> <sec> <name> - Change timestamp of an object */ case 't' : if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) { break; } Finfo.fdate = ((p1 - 1980) << 9) | ((p2 & 15) << 5) | (p3 & 31); if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) { break; } Finfo.ftime = ((p1 & 31) << 11) | ((p2 & 63) << 5) | ((p3 >> 1) & 31); put_rc(f_utime(ptr, &Finfo)); break; #endif #if FILCPY_NOTUSE == 0 case 'x' : /* fx <src_name> <dst_name> - Copy file */ while ( *ptr == ' ' ) { ptr++; } ptr2 = strchr( ptr, ' ' ); if ( !ptr2 ) { break; } *ptr2++ = 0; while ( *ptr2 == ' ' ) { ptr2++; } f_res = f_open( &File1, ptr, FA_OPEN_EXISTING | FA_READ ); PRINTF("Opening %s \r\n", ptr); if ( f_res ) { put_rc( (FRESULT)f_res ); break; } f_res = f_open( &File2, ptr2, FA_CREATE_ALWAYS | FA_WRITE ); PRINTF(" Creating %s \r\n", ptr2); if ( f_res ) { put_rc( (FRESULT)f_res ); f_close( &File1 ); break; } PRINTF("Copying file..."); p1 = 0; for ( ;; ) { f_res = f_read( &File1, Buff, blen, &s1 ); if ( f_res || s1 == 0 ) { break; /* error or eof */ } f_res = f_write( &File2, Buff, s1, &s2 ); p1 += s2; if ( f_res || s2 < s1 ) { break; /* error or disk full */ } } f_close( &File1 ); f_close( &File2 ); crlf(); break; #endif #if 0 case 'x' : /* fx <src.name> <dst.name> - Copy a file */ while (*ptr == ' ') ptr++; ptr2 = strchr(ptr, ' '); if (!ptr2) break; *ptr2++ = 0; while (*ptr2 == ' ') ptr2++; PRINTF("Opening \"%s\"", ptr); res = f_open(&File1, ptr, FA_OPEN_EXISTING | FA_READ); PUTS("\r\n"); if (res) { put_rc((FRESULT)res); break; } PRINTF("Creating \"%s\"", ptr2); res = f_open(&File1, ptr2, FA_CREATE_ALWAYS | FA_WRITE); PUTS("\r\n"); if (res) { put_rc((FRESULT)res); f_close(&File1); break; } PRINTF("Copying file..."); t.reset(); t.start(); p1 = 0; for (;;) { res = f_read(&File1, Buff, blen, &s1); if (res || s1 == 0) break; /* error or eof */ res = f_write(&File2, Buff, s1, &s2); p1 += s2; if (res || s2 < s1) break; /* error or disk full */ } tim = t.read_ms(); PRINTF("\r\n%lu bytes copied with %lu kB/sec.\r\n", p1, tim ? (p1 / tim) : 0); f_close(&File1); f_close(&File2); break; #endif #if FF_FS_RPATH case 'g' : /* fg <path> - Change current directory */ while (*ptr == ' ') ptr++; put_rc(f_chdir(ptr)); break; #if FF_FS_RPATH >= 2 case 'q' : /* fq - Show current dir path */ res = f_getcwd(Linebuf, sizeof Linebuf); if (res) put_rc(res); else PRINTF("%s\r\n", Linebuf); break; #endif #endif #if FF_USE_LABEL case 'b' : /* fb <name> - Set volume label */ while (*ptr == ' ') ptr++; put_rc(f_setlabel(ptr)); break; #endif /* FF_USE_LABEL */ #if FF_USE_MKFS case 'm' : /* fm <type> <csize> - Create file system */ if (!xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break; PRINTF("The volume will be formatted. Are you sure? (Y/n)="); get_line(Linebuf, sizeof Linebuf); if (Linebuf[0] == 'Y') put_rc(f_mkfs("", (BYTE)p2, (DWORD)p3, Buff, sizeof Buff)); break; #endif /* FF_USE_MKFS */ /* fz [<size>] - Change/Show R/W length for fr/fw/fx command */ case 'z' : if (xatoi(&ptr, &p1) && p1 >= 1 && p1 <= (long)sizeof Buff) blen = p1; PRINTF("blen=%u\r\n", blen); break; } } static void memory_inf(char *ptr) { long p1, p2, p3; switch (*ptr++) { case 'd' : /* md[b|h|w] <address> [<count>] - Dump memory */ switch (*ptr++) { case 'w': p3 = DW_LONG; break; case 'h': p3 = DW_SHORT; break; default: p3 = DW_CHAR; } if (!xatoi(&ptr, &p1)) break; if (!xatoi(&ptr, &p2)) p2 = 128 / p3; for (ptr = (char*)p1; p2 >= 16 / p3; ptr += 16, p2 -= 16 / p3) put_dump(ptr, (DWORD)ptr, 16 / p3, p3); if (p2) put_dump((BYTE*)ptr, (UINT)ptr, p2, p3); break; case 'f' : /* mf <address> <value> <count> - Fill memory */ if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) { break; } while (p3--) { *(BYTE*)p1 = (BYTE)p2; p1++; } break; case 'e' : /* me[b|h|w] <address> [<value> ...] - Edit memory */ switch (*ptr++) { /* Get data width */ case 'w': p3 = DW_LONG; break; case 'h': p3 = DW_SHORT; break; default: p3 = DW_CHAR; } if (!xatoi(&ptr, &p1)) break; /* Get start address */ if (xatoi(&ptr, &p2)) { /* 2nd parameter is given (direct mode) */ do { switch (p3) { case DW_LONG: *(DWORD*)p1 = (DWORD)p2; break; case DW_SHORT: *(WORD*)p1 = (WORD)p2; break; default: *(BYTE*)p1 = (BYTE)p2; } p1 += p3; } while (xatoi(&ptr, &p2)); /* Get next value */ break; } for (;;) { /* 2nd parameter is not given (interactive mode) */ switch (p3) { case DW_LONG: PRINTF("%08X 0x%08X-", p1, *(DWORD*)p1); break; case DW_SHORT: PRINTF("%08X 0x%04X-", p1, *(WORD*)p1); break; default: PRINTF("%08X 0x%02X-", p1, *(BYTE*)p1); } ptr = Linebuf; get_line(ptr, sizeof Linebuf); if (*ptr == '.') break; if ((BYTE)*ptr >= ' ') { if (!xatoi(&ptr, &p2)) continue; switch (p3) { case DW_LONG: *(DWORD*)p1 = (DWORD)p2; break; case DW_SHORT: *(WORD*)p1 = (WORD)p2; break; default: *(BYTE*)p1 = (BYTE)p2; } } p1 += p3; } } } static void disk_inf(char *ptr) { long p1, p2; UINT s1; BYTE res, b, drv = 0; DWORD ofs = 0, sect = 0, blk[2]; switch (*ptr++) { case 'd' : /* dd [<pd#> <sect>] - Dump secrtor */ if (!xatoi(&ptr, &p1)) { p1 = drv; p2 = sect; } else { if (!xatoi(&ptr, &p2)) break; } drv = (BYTE)p1; sect = p2; res = disk_read(drv, Buff, sect, 1); if (res) { PRINTF("rc=%d\r\n", (WORD)res); break; } PRINTF("PD#:%u LBA:%lu\r\n", drv, sect++); for (ptr=(char*)Buff, ofs = 0; ofs < 0x200; ptr += 16, ofs += 16) put_dump((BYTE*)ptr, ofs, 16, DW_CHAR); break; case 'i' : /* di <pd#> - Initialize disk */ if (!xatoi(&ptr, &p1)) break; PRINTF("rc=%d\r\n", (WORD)disk_initialize((BYTE)p1)); break; case 's' : /* ds <pd#> - Show disk status */ if (!xatoi(&ptr, &p1)) break; if (disk_ioctl((BYTE)p1, GET_SECTOR_COUNT, &p2) == RES_OK) { PRINTF("Drive size: %lu sectors\r\n", p2); } if (disk_ioctl((BYTE)p1, GET_BLOCK_SIZE, &p2) == RES_OK) { PRINTF("Block size: %lu sectors\r\n", p2); } if (disk_ioctl((BYTE)p1, MMC_GET_TYPE, &b) == RES_OK) { PRINTF("Media type: %u\r\n", b); } if (disk_ioctl((BYTE)p1, MMC_GET_CSD, Buff) == RES_OK) { PUTS("CSD:\r\n"); put_dump(Buff, 0, 16, DW_CHAR); } if (disk_ioctl((BYTE)p1, MMC_GET_CID, Buff) == RES_OK) { PUTS("CID:\r\n"); put_dump(Buff, 0, 16, DW_CHAR); } if (disk_ioctl((BYTE)p1, MMC_GET_OCR, Buff) == RES_OK) { PUTS("OCR:\r\n"); put_dump(Buff, 0, 4, DW_CHAR); } if (disk_ioctl((BYTE)p1, MMC_GET_SDSTAT, Buff) == RES_OK) { PUTS("SD Status:\r\n"); for (s1 = 0; s1 < 64; s1 += 16) { put_dump(Buff+s1, s1, 16, DW_CHAR); } } break; case 'c' : /* Disk ioctl */ switch (*ptr++) { case 's' : /* dcs <pd#> - CTRL_SYNC */ if (!xatoi(&ptr, &p1)) break; PRINTF("rc=%d\r\n", disk_ioctl((BYTE)p1, CTRL_SYNC, 0)); break; case 'e' : /* dce <pd#> <s.lba> <e.lba> - CTRL_TRIM */ if (!xatoi(&ptr, &p1) || !xatoi(&ptr, (long*)&blk[0]) || !xatoi(&ptr, (long*)&blk[1])) { break; } PRINTF("rc=%d\r\n", disk_ioctl((BYTE)p1, CTRL_TRIM, blk)); break; } } } void put_dump ( void* buff, /* Pointer to the array to be dumped */ unsigned long addr, /* Heading address value */ int len, /* Number of items to be dumped */ int width /* Size of the items (DW_CHAR, DW_SHORT, DW_LONG) */ ) { int i; unsigned char *bp; unsigned short *sp; unsigned long *lp; PRINTF( "%08lx ", addr ); /* address */ switch ( width ) { case DW_CHAR: bp = (unsigned char *)buff; for ( i = 0; i < len; i++ ) { /* Hexdecimal dump */ PRINTF( " %02x", bp[i] ); } PUTC(' '); for ( i = 0; i < len; i++ ) { /* ASCII dump */ PUTC( (bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.' ); } break; case DW_SHORT: sp = (unsigned short *)buff; do { /* Hexdecimal dump */ PRINTF( " %04x", *sp++ ); } while ( --len ); break; case DW_LONG: lp = (unsigned long *)buff; do { /* Hexdecimal dump */ PRINTF( " %08lx", *lp++ ); } while ( --len ); break; } PUTS( "\r\n" ); } // RTC related subroutines void chk_and_set_time(char *ptr) { char buf[64]; long p1; struct tm t; time_t seconds; if (xatoi(&ptr, &p1)) { t.tm_year = (uint8_t)p1 + 100; pc.printf("Year:%d ",p1); xatoi( &ptr, &p1 ); t.tm_mon = (uint8_t)p1 - 1; pc.printf("Month:%d ",p1); xatoi( &ptr, &p1 ); t.tm_mday = (uint8_t)p1; pc.printf("Day:%d ",p1); xatoi( &ptr, &p1 ); t.tm_hour = (uint8_t)p1; pc.printf("Hour:%d ",p1); xatoi( &ptr, &p1 ); t.tm_min = (uint8_t)p1; pc.printf("Min:%d ",p1); xatoi( &ptr, &p1 ); t.tm_sec = (uint8_t)p1; pc.printf("Sec: %d \r\n",p1); seconds = mktime(&t); set_time(seconds); } else { seconds = time(NULL); } strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds)); pc.printf("[Time] %s", buf); } // Get key input data void get_line (char *buff, int len) { char c; int idx = 0; for (;;) { c = GETC(); // Added by Kenji Arai / JH1PJL May 9th, 2010 if (c == '\r') { buff[idx++] = c; break; } if ((c == '\b') && idx) { idx--; PUTC(c); PUTC(' '); PUTC(c); } if (((uint8_t)c >= ' ') && (idx < len - 1)) { buff[idx++] = c; PUTC(c); } } buff[idx] = 0; PUTS("\r\n"); } /* Outpur LF & CR */ void crlf( void ) { PRINTF( "\r\n" ); } /* Check key input */ unsigned int check_hit_key (void) { return ( READABLE() ); } /*----------------------------------------------*/ /* Get a value of the string */ /*----------------------------------------------*/ /* "123 -5 0x3ff 0b1111 0377 w " ^ 1st call returns 123 and next ptr ^ 2nd call returns -5 and next ptr ^ 3rd call returns 1023 and next ptr ^ 4th call returns 15 and next ptr ^ 5th call returns 255 and next ptr ^ 6th call fails and returns 0 */ int xatoi ( /* 0:Failed, 1:Successful */ char **str, /* Pointer to pointer to the string */ long *res /* Pointer to the valiable to store the value */ ) { unsigned long val; unsigned char c, r, s = 0; *res = 0; while ( (c = **str) == ' ' ) { (*str)++; /* Skip leading spaces */ } if ( c == '-' ) { /* negative? */ s = 1; c = *(++(*str)); } if ( c == '0' ) { c = *(++(*str)); switch (c) { case 'x': /* hexdecimal */ r = 16; c = *(++(*str)); break; case 'b': /* binary */ r = 2; c = *(++(*str)); break; default: if ( c <= ' ' ) return 1; /* single zero */ if ( c < '0' || c > '9' ) return 0; /* invalid char */ r = 8; /* octal */ } } else { if ( c < '0' || c > '9' ) return 0; /* EOL or invalid char */ r = 10; /* decimal */ } val = 0; while ( c > ' ' ) { if ( c >= 'a' ) { c -= 0x20; } c -= '0'; if ( c >= 17 ) { c -= 7; if ( c <= 9 ) { return 0; /* invalid char */ } } if ( c >= r ) { return 0; /* invalid char for current radix */ } val = val * r + c; c = *(++(*str)); } if (s) val = 0 - val; /* apply sign if needed */ *res = val; return 1; }