microSD Card control function for DISCO-F469NI based on BD_SD_DISCO_F746NG library by Roy Krikke
Dependencies: BSP_DISCO_F469NI_modified BD_SD_DISCO_F469NI
Fork of DISCO-F769NI_BD_SD_Card_Control by
Please refer following my Notebook page.
/users/kenjiArai/notebook/sd-card-control-new/
Diff: FatFs_Mon/mon.cpp
- Revision:
- 4:0f7797c2d3fe
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFs_Mon/mon.cpp Sat Apr 07 02:10:18 2018 +0000 @@ -0,0 +1,1228 @@ +/* + * 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; +}