From 75e1e7a5e26491e942fb2b25f518d8e2e3112721 Mon Sep 17 00:00:00 2001 From: inmarket Date: Fri, 15 Aug 2014 02:22:02 +1000 Subject: Add GFILE support for PetitFS (a very tiny FAT implementation) --- src/gfile/inc_petitfs.c | 157 +++++++++++++++++++++++++++++++++++++ src/gfile/petitfs_chibios_diskio.c | 82 +++++++++++++++++++ src/gfile/petitfs_wrapper.c | 23 ++++++ src/gfile/petitfs_wrapper.h | 26 ++++++ src/gfile/sys_make.mk | 7 +- src/gfile/sys_options.h | 22 +++++- src/gfile/sys_rules.h | 3 + 7 files changed, 317 insertions(+), 3 deletions(-) create mode 100644 src/gfile/inc_petitfs.c create mode 100644 src/gfile/petitfs_chibios_diskio.c create mode 100644 src/gfile/petitfs_wrapper.c create mode 100644 src/gfile/petitfs_wrapper.h (limited to 'src/gfile') diff --git a/src/gfile/inc_petitfs.c b/src/gfile/inc_petitfs.c new file mode 100644 index 00000000..9b3b510b --- /dev/null +++ b/src/gfile/inc_petitfs.c @@ -0,0 +1,157 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/******************************************************** + * The PETITFS file-system + ********************************************************/ + +#include "gfx.h" + +#if GFX_USE_GFILE && GFILE_NEED_PETITFS + +#include "gfile_fs.h" +#include "petitfs_wrapper.h" + +static bool_t petitfsExists(const char* fname); +static bool_t petitfsOpen(GFILE* f, const char* fname); +static int petitfsRead(GFILE* f, void* buf, int size); +static bool_t petitfsSetPos(GFILE* f, long int pos); +#if GFILE_NEED_FILELISTS && _FS_MINIMIZE <= 1 + static gfileList *petitfsFlOpen(const char *path, bool_t dirs); + static const char *petitfsFlRead(gfileList *pfl); + static void petitfsFlClose(gfileList *pfl); +#endif + +const GFILEVMT FsPetitFSVMT = { + GFSFLG_WRITEABLE | GFSFLG_SEEKABLE, + 'F', + 0, + petitfsExists, + 0, // No Filesize + 0, + petitfsOpen, + 0, // No Close + petitfsRead, + 0, // No Write + petitfsSetPos, + 0, // No Getsize + 0, // No EOF + 0, 0, 0, // No Mount, UnMount or Sync + #if GFILE_NEED_FILELISTS + #if _USE_DIR + petitfsFlOpen, petitfsFlRead, petitfsFlClose + #else + 0, 0, 0 + #endif + #endif +}; + +// Our directory list structure +typedef struct petitfsList { + gfileList fl; // This must be the first element. + DIR dir; + FILINFO fno; +} petitfsList; + +// optimize these later on. Use an array to have multiple +static bool_t petitfs_mounted = FALSE; +static FATFS petitfs_fs; + +static bool_t petitfsExists(const char* fname) +{ + // Mount first + if (!petitfs_mounted && pf_mount(&petitfs_fs) != FR_OK) + return FALSE; + + // Open + if (pf_open(fname) != FR_OK) + return FALSE; + + return TRUE; +} + +static bool_t petitfsOpen(GFILE* f, const char* fname) +{ + // No writing + if ((f->flags & GFILEFLG_WRITE)) + return FALSE; + + // Mount first + if (!petitfs_mounted && pf_mount(&petitfs_fs) != FR_OK) + return FALSE; + + // Open + if (pf_open(fname) != FR_OK) + return FALSE; + + f->obj = &petitfs_fs; + return TRUE; +} + +static int petitfsRead(GFILE* f, void* buf, int size) +{ + int br; + (void) f; + + if (pf_read(buf, size, (UINT*)&br) != FR_OK) + return 0; + + return br; +} + +static bool_t petitfsSetPos(GFILE* f, long int pos) +{ + (void) f; + return pf_lseek((DWORD)pos) == FR_OK; +} + +#if GFILE_NEED_FILELISTS + static gfileList *petitfsFlOpen(const char *path, bool_t dirs) { + petitfsList *p; + (void) dirs; + + if (!(p = gfxAlloc(sizeof(petitfsList)))) + return 0; + + if (pf_opendir(&p->dir, path) != FR_OK) { + gfxFree(p); + return 0; + } + return &p->fl; + } + + static const char *petitfsFlRead(gfileList *pfl) { + #define ffl ((petitfsList *)pfl) + + while(1) { + // Read the next entry + if (pf_readdir(&ffl->dir, &ffl->fno) != FR_OK || !ffl->fno.fname[0]) + return 0; + + /* Ignore dot entries */ + if (ffl->fno.fname[0] == '.') continue; + + /* Is it a directory */ + if (ffl->fl.dirs) { + if ((ffl->fno.fattrib & AM_DIR)) + break; + } else { + if (!(ffl->fno.fattrib & (AM_DIR|AM_HID|AM_SYS))) + break; + } + } + + return ffl->fno.fname; + } + + static void petitfsFlClose(gfileList *pfl) { + gfxFree(pfl); + } + +#endif + +#endif //GFX_USE_GFILE && GFILE_NEED_PETITFS diff --git a/src/gfile/petitfs_chibios_diskio.c b/src/gfile/petitfs_chibios_diskio.c new file mode 100644 index 00000000..dda3f6fc --- /dev/null +++ b/src/gfile/petitfs_chibios_diskio.c @@ -0,0 +1,82 @@ +/*-----------------------------------------------------------------------*/ +/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */ +/*-----------------------------------------------------------------------*/ +/* This is a stub disk I/O module that acts as front end of the existing */ +/* disk I/O modules and attach it to FatFs module with common interface. */ +/*-----------------------------------------------------------------------*/ + +#include "gfx.h" + +#if GFX_USE_GFILE && GFILE_NEED_PETITFS && GFX_USE_OS_CHIBIOS + +#include "petitfs_wrapper.h" + +#include + +#if HAL_USE_MMC_SPI && HAL_USE_SDC +#error "cannot specify both MMC_SPI and SDC drivers" +#endif + +#if HAL_USE_MMC_SPI +extern MMCDriver MMCD1; +#elif HAL_USE_SDC +extern SDCDriver SDCD1; +#else +#error "MMC_SPI or SDC driver must be specified" +#endif + +/*-----------------------------------------------------------------------*/ +/* Initialize a Drive */ + +DSTATUS disk_initialize (void) { +#if HAL_USE_MMC_SPI + /* It is initialized externally, just reads the status.*/ + if (blkGetDriverState(&MMCD1) != BLK_READY) + return STA_NOINIT; +#else + /* It is initialized externally, just reads the status.*/ + if (blkGetDriverState(&SDCD1) != BLK_READY) + return STA_NOINIT; +#endif + // All good + return 0; +} + +/*-----------------------------------------------------------------------*/ +/* Read Part Sector(s) */ + +static BYTE sectBuf[512]; +static DWORD sectpos = -1; + +DRESULT disk_readp ( + BYTE* buff, /* [OUT] Pointer to the read buffer */ + DWORD sector, /* [IN] Sector number */ + UINT offset, /* [IN] Byte offset in the sector to start to read */ + UINT count /* [IN] Number of bytes to read */ + ) { + + if (sector != sectpos) { + #if HAL_USE_MMC_SPI + if (blkGetDriverState(&MMCD1) != BLK_READY) + return RES_NOTRDY; + if (mmcStartSequentialRead(&MMCD1, sector)) + return RES_ERROR; + if (mmcSequentialRead(&MMCD1, sectBuf)) + return RES_ERROR; + if (mmcStopSequentialRead(&MMCD1)) + return RES_ERROR; + #else + if (blkGetDriverState(&SDCD1) != BLK_READY) + return RES_NOTRDY; + if (sdcRead(&SDCD1, sector, sectBuf, 1)) + return RES_ERROR; + #endif + sectpos = sector; + } + memcpy(buff, sectBuf + offset, count); + return RES_OK; +} + +#endif // GFX_USE_GFILE && GFILE_NEED_PETITFS && GFX_USE_OS_CHIBIOS + + diff --git a/src/gfile/petitfs_wrapper.c b/src/gfile/petitfs_wrapper.c new file mode 100644 index 00000000..183edb70 --- /dev/null +++ b/src/gfile/petitfs_wrapper.c @@ -0,0 +1,23 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file src/gfile/petitfs_wrapper.c + * @brief GFILE PETITFS wrapper. + * + */ + +#include "gfx.h" + +#if GFX_USE_GFILE && GFILE_NEED_PETITFS + +#include "petitfs_wrapper.h" + +// Include the source we want +#include "3rdparty/petitfs-0.03/src/pff.c" + +#endif // GFX_USE_GFILE && GFILE_NEED_PETITFS diff --git a/src/gfile/petitfs_wrapper.h b/src/gfile/petitfs_wrapper.h new file mode 100644 index 00000000..4f91bd7f --- /dev/null +++ b/src/gfile/petitfs_wrapper.h @@ -0,0 +1,26 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file src/gfile/petitfs_wrapper.h + * @brief GFILE PETITFS wrapper. + * + */ + +#ifndef _PETITFS_WRAPPER +#define _PETITFS_WRAPPER + +// Include the petitfs configuration from the local directory not the original source folder +#include "pffconf.h" + +// Include the petitfs API +#include "3rdparty/petitfs-0.03/src/pff.h" + +// Include the petitfs diskio API +#include "3rdparty/petitfs-0.03/src/diskio.h" + +#endif //_PETITFS_WRAPPER diff --git a/src/gfile/sys_make.mk b/src/gfile/sys_make.mk index ba74a15c..e14527c6 100644 --- a/src/gfile/sys_make.mk +++ b/src/gfile/sys_make.mk @@ -3,6 +3,7 @@ GFXSRC += $(GFXLIB)/src/gfile/gfile.c \ $(GFXLIB)/src/gfile/inc_ramfs.c \ $(GFXLIB)/src/gfile/inc_romfs.c \ $(GFXLIB)/src/gfile/inc_fatfs.c \ + $(GFXLIB)/src/gfile/inc_petitfs.c \ $(GFXLIB)/src/gfile/inc_memfs.c \ $(GFXLIB)/src/gfile/inc_chibiosfs.c \ $(GFXLIB)/src/gfile/inc_strings.c \ @@ -10,4 +11,8 @@ GFXSRC += $(GFXLIB)/src/gfile/gfile.c \ $(GFXLIB)/src/gfile/inc_scang.c \ $(GFXLIB)/src/gfile/inc_stdio.c \ $(GFXLIB)/src/gfile/fatfs_wrapper.c \ - $(GFXLIB)/src/gfile/fatfs_chibios_diskio.c + $(GFXLIB)/src/gfile/fatfs_chibios_diskio.c \ + $(GFXLIB)/src/gfile/petitfs_wrapper.c \ + $(GFXLIB)/src/gfile/petitfs_chibios_diskio.c \ + + \ No newline at end of file diff --git a/src/gfile/sys_options.h b/src/gfile/sys_options.h index ff1e5d4c..354d4f2b 100644 --- a/src/gfile/sys_options.h +++ b/src/gfile/sys_options.h @@ -101,16 +101,34 @@ #define GFILE_NEED_RAMFS FALSE #endif /** - * @brief Include the FAT file system driver + * @brief Include the FAT file system driver based on the FATFS library * @details Defaults to FALSE * @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are * opening a file on the FAT file system by prefixing * its name with "F|" (the letter 'F', followed by a vertical bar). - * @note You must separately include the FATFS library and code. + * @note FATFS and PETITFS offer the same FAT file system support. They just use + * different constraints. PETITFS is smaller but has less features. Only + * one can be used at a time. The block interfaces are also different. */ #ifndef GFILE_NEED_FATFS #define GFILE_NEED_FATFS FALSE #endif + /** + * @brief Include the FAT file system driver based on the PETITFS library + * @details Defaults to FALSE + * @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are + * opening a file on the FAT file system by prefixing + * its name with "F|" (the letter 'F', followed by a vertical bar). + * @note FATFS and PETITFS offer the same FAT file system support. They just use + * different constraints. PETITFS is smaller but has less features. Only + * one can be used at a time. The block interfaces are also different. + * @note Due to the restrictions on the PETITFS library on writing, we do not implement + * writing. + * @note PETITFS can only have one file open at a time. + */ + #ifndef GFILE_NEED_PETITFS + #define GFILE_NEED_FATFS FALSE + #endif /** * @brief Include the operating system's native file system * @details Defaults to FALSE diff --git a/src/gfile/sys_rules.h b/src/gfile/sys_rules.h index 8d07144d..d13041f2 100644 --- a/src/gfile/sys_rules.h +++ b/src/gfile/sys_rules.h @@ -17,6 +17,9 @@ #define _GFILE_RULES_H #if GFX_USE_GFILE + #if GFILE_NEED_PETITFS && GFILE_NEED_FATFS + #error "GFILE: Both GFILE_NEED_PETITFS and GFILE_NEED_FATFS cannot both be turned on at the same time." + #endif #endif #endif /* _GFILE_RULES_H */ -- cgit v1.2.3