/*----------------------------------------------------------------------*/ /* FAT file system sample project for FatFs R0.07 (C)ChaN, 2008 */ /*----------------------------------------------------------------------*/ #include #include "LPC2300.h" #include "integer.h" #include "interrupt.h" #include "comm.h" #include "monitor.h" #include "rtc.h" #include "diskio.h" #include "ff.h" DWORD acc_size; /* Work register for fs command */ WORD acc_files, acc_dirs; FILINFO Finfo; #if _USE_LFN char Lfname[512]; #endif char linebuf[120]; /* Console input buffer */ FATFS Fatfs[_DRIVES]; /* File system object for each logical drive */ FIL File1, File2; /* File objects */ DIR Dir; /* Directory object */ BYTE Buff[16384] __attribute__ ((aligned (4))) ; /* Working buffer */ volatile UINT Timer; /* Performance timer (1kHz increment) */ /*---------------------------------------------------------*/ /* 1000Hz timer interrupt generated by TIMER0 */ /*---------------------------------------------------------*/ void Isr_TIMER0 (void) { T0IR = 1; /* Clear irq flag */ Timer++; disk_timerproc(); /* Disk timer process */ } /*---------------------------------------------------------*/ /* User Provided Timer Function for FatFs module */ /*---------------------------------------------------------*/ /* This is a real time clock service to be called from */ /* FatFs module. Any valid time must be returned even if */ /* the system does not support a real time clock. */ /* This is not required in read-only configuration. */ DWORD get_fattime () { RTC rtc; rtc_gettime(&rtc); return ((DWORD)(rtc.year - 1980) << 25) | ((DWORD)rtc.month << 21) | ((DWORD)rtc.mday << 16) | ((DWORD)rtc.hour << 11) | ((DWORD)rtc.min << 5) | ((DWORD)rtc.sec >> 1); } /*--------------------------------------------------------------------------*/ /* Monitor */ /*--------------------------------------------------------------------------*/ static FRESULT scan_files (char* path) { DIR dirs; FRESULT res; BYTE i; char *fn; if ((res = f_opendir(&dirs, path)) == FR_OK) { i = strlen(path); while (((res = f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) { #if _USE_LFN fn = *Finfo.lfname ? Finfo.lfname : Finfo.fname; #else fn = Finfo.fname; #endif if (Finfo.fattrib & AM_DIR) { acc_dirs++; *(path+i) = '/'; strcpy(path+i+1, fn); res = scan_files(path); *(path+i) = '\0'; if (res != FR_OK) break; } else { // xprintf("%s/%s\n", path, fn); acc_files++; acc_size += Finfo.fsize; } } } return res; } static void put_rc (FRESULT rc) { const char *p; static const char str[] = "OK\0" "NOT_READY\0" "NO_FILE\0" "FR_NO_PATH\0" "INVALID_NAME\0" "INVALID_DRIVE\0" "DENIED\0" "EXIST\0" "RW_ERROR\0" "WRITE_PROTECTED\0" "NOT_ENABLED\0" "NO_FILESYSTEM\0" "INVALID_OBJECT\0" "MKFS_ABORTED\0"; FRESULT i; for (p = str, i = 0; i != rc && *p; i++) { while(*p++); } xprintf("rc=%u FR_%s\n", (UINT)rc, p); } static void IoInit (void) { #define PLL_N 2UL #define PLL_M 72UL #define CCLK_DIV 4 if ( PLLSTAT & (1 << 25) ) { PLLCON = 1; /* Disconnect PLL output if PLL is in use */ PLLFEED = 0xAA; PLLFEED = 0x55; } PLLCON = 0; /* Disable PLL */ PLLFEED = 0xAA; PLLFEED = 0x55; CLKSRCSEL = 0; /* Select IRC (4MHz) as the PLL clock source */ PLLCFG = ((PLL_N - 1) << 16) | (PLL_M - 1); /* Re-configure PLL */ PLLFEED = 0xAA; PLLFEED = 0x55; PLLCON = 1; /* Enable PLL */ PLLFEED = 0xAA; PLLFEED = 0x55; while ((PLLSTAT & (1 << 26)) == 0); /* Wait for PLL locked */ CCLKCFG = CCLK_DIV-1; /* Select CCLK frequency (divide ratio of hclk) */ PLLCON = 3; /* Connect PLL output to the sysclk */ PLLFEED = 0xAA; PLLFEED = 0x55; MAMCR = 0; /* Configure MAM for 72MHz operation */ MAMTIM = 3; MAMCR = 2; PCLKSEL0 = 0x00000000; /* Initialize peripheral clock to default */ PCLKSEL1 = 0x00000000; ClearVector(); /* Initialie VIC */ SCS |= 1; /* Enable FIO0 and FIO1 */ FIO1DIR0 = 0x10; /* -|-|-|LEDR|-|-|-|- */ FIO1PIN0 = 0x00; /* Initialize Timer0 as 1kHz interval timer */ RegisterVector(TIMER0_INT, Isr_TIMER0, PRI_LOWEST, CLASS_IRQ); T0CTCR = 0; T0MR0 = 18000 - 1; /* 18M / 1k = 18000 */ T0MCR = 0x3; /* Clear TC and Interrupt on MR0 match */ T0TCR = 1; uart0_init(); /* Initialize UART0 */ IrqEnable(); /* Enable Irq */ } int main (void) { char *ptr, *ptr2; long p1, p2, p3; BYTE res, b1; WORD w1; UINT s1, s2, cnt, blen = sizeof(Buff); DWORD ofs = 0, sect = 0; FATFS *fs; /* Pointer to file system object */ RTC rtc; IoInit(); xputs("\nFatFs module test monitor for LPC2368\n"); for (;;) { xputc('>'); ptr = linebuf; get_line(ptr, sizeof(linebuf)); switch (*ptr++) { case 'm' : switch (*ptr++) { case 'd' : /* md
[] - Dump memory */ if (!xatoi(&ptr, &p1)) break; if (!xatoi(&ptr, &p2)) p2 = 128; for (ptr=(char*)p1; p2 >= 16; ptr += 16, p2 -= 16) put_dump((BYTE*)ptr, (UINT)ptr, 16); if (p2) put_dump((BYTE*)ptr, (UINT)ptr, p2); break; } break; case 'd' : switch (*ptr++) { case 'd' : /* dd [] - Dump secrtor */ if (!xatoi(&ptr, &p2)) p2 = sect; res = disk_read(0, Buff, p2, 1); if (res) { xprintf("rc=%d\n", (WORD)res); break; } sect = p2 + 1; xprintf("Sector:%lu\n", p2); for (ptr=(char*)Buff, ofs = 0; ofs < 0x200; ptr+=16, ofs+=16) put_dump((BYTE*)ptr, ofs, 16); break; case 'i' : /* di - Initialize disk */ xprintf("rc=%d\n", (WORD)disk_initialize(0)); break; case 's' : /* ds - Show disk status */ if (disk_ioctl(0, GET_SECTOR_COUNT, &p2) == RES_OK) { xprintf("Drive size: %lu sectors\n", p2); } if (disk_ioctl(0, GET_SECTOR_SIZE, &w1) == RES_OK) { xprintf("Sector size: %u\n", w1); } if (disk_ioctl(0, GET_BLOCK_SIZE, &p2) == RES_OK) { xprintf("Erase block size: %lu sectors\n", p2); } if (disk_ioctl(0, MMC_GET_TYPE, &b1) == RES_OK) { xprintf("MMC/SDC type: %u\n", b1); } if (disk_ioctl(0, MMC_GET_CSD, Buff) == RES_OK) { xputs("CSD:\n"); put_dump(Buff, 0, 16); } if (disk_ioctl(0, MMC_GET_CID, Buff) == RES_OK) { xputs("CID:\n"); put_dump(Buff, 0, 16); } if (disk_ioctl(0, MMC_GET_OCR, Buff) == RES_OK) { xputs("OCR:\n"); put_dump(Buff, 0, 4); } if (disk_ioctl(0, MMC_GET_SDSTAT, Buff) == RES_OK) { xputs("SD Status:\n"); for (s1 = 0; s1 < 64; s1 += 16) put_dump(Buff+s1, s1, 16); } break; } break; case 'b' : switch (*ptr++) { case 'd' : /* bd - Dump R/W buffer */ if (!xatoi(&ptr, &p1)) break; for (ptr=(char*)&Buff[p1], ofs = p1, cnt = 32; cnt; cnt--, ptr+=16, ofs+=16) put_dump((BYTE*)ptr, ofs, 16); break; case 'e' : /* be [] ... - Edit R/W buffer */ if (!xatoi(&ptr, &p1)) break; if (xatoi(&ptr, &p2)) { do { Buff[p1++] = (BYTE)p2; } while (xatoi(&ptr, &p2)); break; } for (;;) { xprintf("%04X %02X-", (WORD)(p1), (WORD)Buff[p1]); get_line(linebuf, sizeof(linebuf)); ptr = linebuf; if (*ptr == '.') break; if (*ptr < ' ') { p1++; continue; } if (xatoi(&ptr, &p2)) Buff[p1++] = (BYTE)p2; else xputs("???\n"); } break; case 'r' : /* br [] - Read disk into R/W buffer */ if (!xatoi(&ptr, &p2)) break; if (!xatoi(&ptr, &p3)) p3 = 1; xprintf("rc=%u\n", (WORD)disk_read(0, Buff, p2, p3)); break; case 'w' : /* bw [] - Write R/W buffer into disk */ if (!xatoi(&ptr, &p2)) break; if (!xatoi(&ptr, &p3)) p3 = 1; xprintf("rc=%u\n", (WORD)disk_write(0, Buff, p2, p3)); break; case 'f' : /* bf - Fill working buffer */ if (!xatoi(&ptr, &p1)) break; memset(Buff, (BYTE)p1, sizeof(Buff)); break; } break; case 'f' : switch (*ptr++) { case 'i' : /* fi - Force initialized the logical drive */ put_rc(f_mount(0, &Fatfs[0])); break; case 's' : /* fs - Show logical drive status */ res = f_getfree("", (DWORD*)&p2, &fs); if (res) { put_rc(res); break; } xprintf("FAT type = %u\nBytes/Cluster = %lu\nNumber of FATs = %u\n" "Root DIR entries = %u\nSectors/FAT = %lu\nNumber of clusters = %lu\n" "FAT start (lba) = %lu\nDIR start (lba,clustor) = %lu\nData start (lba) = %lu\n\n", (WORD)fs->fs_type, (DWORD)fs->csize * 512, (WORD)fs->n_fats, fs->n_rootdir, fs->sects_fat, (DWORD)fs->max_clust - 2, fs->fatbase, fs->dirbase, fs->database ); acc_size = acc_files = acc_dirs = 0; #if _USE_LFN Finfo.lfname = Lfname; Finfo.lfsize = sizeof(Lfname); #endif res = scan_files(ptr); if (res) { put_rc(res); break; } xprintf("%u files, %lu bytes.\n%u folders.\n" "%lu KB total disk space.\n%lu KB available.\n", acc_files, acc_size, acc_dirs, (fs->max_clust - 2) * (fs->csize / 2), p2 * (fs->csize / 2) ); break; case 'l' : /* fl [] - Directory listing */ while (*ptr == ' ') ptr++; res = f_opendir(&Dir, ptr); if (res) { put_rc(res); break; } p1 = s1 = s2 = 0; for(;;) { #if _USE_LFN Finfo.lfname = Lfname; Finfo.lfsize = sizeof(Lfname); #endif res = f_readdir(&Dir, &Finfo); if ((res != FR_OK) || !Finfo.fname[0]) break; if (Finfo.fattrib & AM_DIR) { s2++; } else { s1++; p1 += Finfo.fsize; } xprintf("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %s", (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[0])); #if _USE_LFN xprintf(" %s\n", Lfname); #else xputc('\n'); #endif } xprintf("%4u File(s),%10lu bytes total\n%4u Dir(s)", s1, p1, s2); if (f_getfree(ptr, (DWORD*)&p1, &fs) == FR_OK) xprintf(", %10lu bytes free\n", p1 * fs->csize * 512); break; case 'o' : /* fo - Open a file */ if (!xatoi(&ptr, &p1)) break; while (*ptr == ' ') ptr++; put_rc(f_open(&File1, ptr, (BYTE)p1)); 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(res); if (res == FR_OK) xprintf("fptr=%lu(0x%lX)\n", File1.fptr, File1.fptr); break; case 'd' : /* fd - 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(res); break; } if (!cnt) break; put_dump(Buff, ofs, cnt); ofs += 16; } break; case 'r' : /* fr - read file */ if (!xatoi(&ptr, &p1)) break; p2 = 0; Timer = 0; 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(res); break; } p2 += s2; if (cnt != s2) break; } xprintf("%lu bytes read with %lu kB/sec.\n", p2, p2 / Timer); break; case 'w' : /* fw - write file */ if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break; memset(Buff, (BYTE)p2, blen); p2 = 0; Timer = 0; 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(res); break; } p2 += s2; if (cnt != s2) break; } xprintf("%lu bytes written with %lu kB/sec.\n", p2, p2 / Timer); break; case 'n' : /* fn - Change file/dir name */ while (*ptr == ' ') ptr++; ptr2 = strchr(ptr, ' '); if (!ptr2) break; *ptr2++ = 0; while (*ptr2 == ' ') ptr2++; put_rc(f_rename(ptr, ptr2)); break; case 'u' : /* fu - Unlink a file or dir */ while (*ptr == ' ') ptr++; put_rc(f_unlink(ptr)); break; case 'v' : /* fv - Truncate file */ put_rc(f_truncate(&File1)); break; case 'k' : /* fk - Create a directory */ while (*ptr == ' ') ptr++; put_rc(f_mkdir(ptr)); break; case 'a' : /* fa - Change file/dir attribute */ if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break; while (*ptr == ' ') ptr++; put_rc(f_chmod(ptr, p1, p2)); break; case 't' : /* ft - Change timestamp */ 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) | ((p1 & 63) << 5) | ((p1 >> 1) & 31); put_rc(f_utime(ptr, &Finfo)); break; case 'x' : /* fx - Copy file */ while (*ptr == ' ') ptr++; ptr2 = strchr(ptr, ' '); if (!ptr2) break; *ptr2++ = 0; while (*ptr2 == ' ') ptr2++; xprintf("Opening \"%s\"", ptr); res = f_open(&File1, ptr, FA_OPEN_EXISTING | FA_READ); xputc('\n'); if (res) { put_rc(res); break; } xprintf("Creating \"%s\"", ptr2); res = f_open(&File2, ptr2, FA_CREATE_ALWAYS | FA_WRITE); xputc('\n'); if (res) { put_rc(res); f_close(&File1); break; } xprintf("Copying file..."); Timer = 0; 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 */ } xprintf("%lu bytes copied with %lu kB/sec.\n", p1, p1 / Timer); f_close(&File1); f_close(&File2); break; #if _USE_MKFS case 'm' : /* fm - Create file system */ if (!xatoi(&ptr, &p2) || !xatoi(&ptr, &p3)) break; xprintf("The drive 0 will be formatted. Are you sure? (Y/n)="); get_line(ptr, sizeof(linebuf)); if (*ptr == 'Y') put_rc(f_mkfs(0, (BYTE)p2, (WORD)p3)); break; #endif case 'z' : /* fz [] - Change R/W length for fr/fw/fx command */ if (xatoi(&ptr, &p1) && p1 >= 1 && p1 <= sizeof(Buff)) blen = p1; xprintf("blen=%u\n", blen); break; } break; case 't' : /* t [ ] */ if (xatoi(&ptr, &p1)) { rtc.year = (WORD)p1; xatoi(&ptr, &p1); rtc.month = (BYTE)p1; xatoi(&ptr, &p1); rtc.mday = (BYTE)p1; xatoi(&ptr, &p1); rtc.hour = (BYTE)p1; xatoi(&ptr, &p1); rtc.min = (BYTE)p1; if (!xatoi(&ptr, &p1)) break; rtc.sec = (BYTE)p1; rtc_settime(&rtc); } rtc_gettime(&rtc); xprintf("%u/%u/%u %02u:%02u:%02u\n", rtc.year, rtc.month, rtc.mday, rtc.hour, rtc.min, rtc.sec); break; } } }