From b054a7220f5d6461f9485f18419f27f14708c81c Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Wed, 25 Jun 2014 05:23:57 +0200 Subject: [PATCH] initial implementation - untested --- src/gfile/fatfs/fatfs.mk | 6 + src/gfile/fatfs/readme.txt | 4 - src/gfile/fatfs/src/chibios_fatfs_diskio.c | 254 ++++++++++++++++++++ src/gfile/fatfs/src/chibios_fatfs_syscall.c | 84 +++++++ src/gfile/gfile.c | 2 +- src/gfile/inc_fatfs.c | 75 +++++- src/gfile/sys_make.mk | 3 + 7 files changed, 420 insertions(+), 8 deletions(-) create mode 100644 src/gfile/fatfs/fatfs.mk delete mode 100644 src/gfile/fatfs/readme.txt create mode 100644 src/gfile/fatfs/src/chibios_fatfs_diskio.c create mode 100644 src/gfile/fatfs/src/chibios_fatfs_syscall.c diff --git a/src/gfile/fatfs/fatfs.mk b/src/gfile/fatfs/fatfs.mk new file mode 100644 index 00000000..279ae56f --- /dev/null +++ b/src/gfile/fatfs/fatfs.mk @@ -0,0 +1,6 @@ +GFXSRC += $(GFXLIB)/src/gfile/fatfs/src/ff.c \ + $(GFXLIB)/src/gfile/fatfs/src/chibios_fatfs_diskio.c \ + $(GFXLIB)/src/gfile/fatfs/src/chibios_fatfs_syscall.c + +GFXINC += $(GFXLIB)/src/gfile/fatfs/src + diff --git a/src/gfile/fatfs/readme.txt b/src/gfile/fatfs/readme.txt deleted file mode 100644 index 489327c4..00000000 --- a/src/gfile/fatfs/readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -The contents of this directory are not part of the Works of the -uGFX library. All the contents in this directory are 3rdparty and come with -their own licenses. - diff --git a/src/gfile/fatfs/src/chibios_fatfs_diskio.c b/src/gfile/fatfs/src/chibios_fatfs_diskio.c new file mode 100644 index 00000000..f882aa41 --- /dev/null +++ b/src/gfile/fatfs/src/chibios_fatfs_diskio.c @@ -0,0 +1,254 @@ +/*-----------------------------------------------------------------------*/ +/* 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 "ch.h" +#include "hal.h" +#include "ffconf.h" +#include "diskio.h" + +#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 + +#if HAL_USE_RTC +#include "chrtclib.h" +extern RTCDriver RTCD1; +#endif + +/*-----------------------------------------------------------------------*/ +/* Correspondence between physical drive number and physical drive. */ + +#define MMC 0 +#define SDC 0 + + + +/*-----------------------------------------------------------------------*/ +/* Inidialize a Drive */ + +DSTATUS disk_initialize ( + BYTE drv /* Physical drive nmuber (0..) */ +) +{ + DSTATUS stat; + + switch (drv) { +#if HAL_USE_MMC_SPI + case MMC: + stat = 0; + /* It is initialized externally, just reads the status.*/ + if (blkGetDriverState(&MMCD1) != BLK_READY) + stat |= STA_NOINIT; + if (mmcIsWriteProtected(&MMCD1)) + stat |= STA_PROTECT; + return stat; +#else + case SDC: + stat = 0; + /* It is initialized externally, just reads the status.*/ + if (blkGetDriverState(&SDCD1) != BLK_READY) + stat |= STA_NOINIT; + if (sdcIsWriteProtected(&SDCD1)) + stat |= STA_PROTECT; + return stat; +#endif + } + return STA_NODISK; +} + + + +/*-----------------------------------------------------------------------*/ +/* Return Disk Status */ + +DSTATUS disk_status ( + BYTE drv /* Physical drive nmuber (0..) */ +) +{ + DSTATUS stat; + + switch (drv) { +#if HAL_USE_MMC_SPI + case MMC: + stat = 0; + /* It is initialized externally, just reads the status.*/ + if (blkGetDriverState(&MMCD1) != BLK_READY) + stat |= STA_NOINIT; + if (mmcIsWriteProtected(&MMCD1)) + stat |= STA_PROTECT; + return stat; +#else + case SDC: + stat = 0; + /* It is initialized externally, just reads the status.*/ + if (blkGetDriverState(&SDCD1) != BLK_READY) + stat |= STA_NOINIT; + if (sdcIsWriteProtected(&SDCD1)) + stat |= STA_PROTECT; + return stat; +#endif + } + return STA_NODISK; +} + + + +/*-----------------------------------------------------------------------*/ +/* Read Sector(s) */ + +DRESULT disk_read ( + BYTE drv, /* Physical drive nmuber (0..) */ + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Sector address (LBA) */ + UINT count /* Number of sectors to read (1..255) */ +) +{ + switch (drv) { +#if HAL_USE_MMC_SPI + case MMC: + if (blkGetDriverState(&MMCD1) != BLK_READY) + return RES_NOTRDY; + if (mmcStartSequentialRead(&MMCD1, sector)) + return RES_ERROR; + while (count > 0) { + if (mmcSequentialRead(&MMCD1, buff)) + return RES_ERROR; + buff += MMCSD_BLOCK_SIZE; + count--; + } + if (mmcStopSequentialRead(&MMCD1)) + return RES_ERROR; + return RES_OK; +#else + case SDC: + if (blkGetDriverState(&SDCD1) != BLK_READY) + return RES_NOTRDY; + if (sdcRead(&SDCD1, sector, buff, count)) + return RES_ERROR; + return RES_OK; +#endif + } + return RES_PARERR; +} + + + +/*-----------------------------------------------------------------------*/ +/* Write Sector(s) */ + +#if _READONLY == 0 +DRESULT disk_write ( + BYTE drv, /* Physical drive nmuber (0..) */ + const BYTE *buff, /* Data to be written */ + DWORD sector, /* Sector address (LBA) */ + UINT count /* Number of sectors to write (1..255) */ +) +{ + switch (drv) { +#if HAL_USE_MMC_SPI + case MMC: + if (blkGetDriverState(&MMCD1) != BLK_READY) + return RES_NOTRDY; + if (mmcIsWriteProtected(&MMCD1)) + return RES_WRPRT; + if (mmcStartSequentialWrite(&MMCD1, sector)) + return RES_ERROR; + while (count > 0) { + if (mmcSequentialWrite(&MMCD1, buff)) + return RES_ERROR; + buff += MMCSD_BLOCK_SIZE; + count--; + } + if (mmcStopSequentialWrite(&MMCD1)) + return RES_ERROR; + return RES_OK; +#else + case SDC: + if (blkGetDriverState(&SDCD1) != BLK_READY) + return RES_NOTRDY; + if (sdcWrite(&SDCD1, sector, buff, count)) + return RES_ERROR; + return RES_OK; +#endif + } + return RES_PARERR; +} +#endif /* _READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous Functions */ + +DRESULT disk_ioctl ( + BYTE drv, /* Physical drive nmuber (0..) */ + BYTE ctrl, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + switch (drv) { +#if HAL_USE_MMC_SPI + case MMC: + switch (ctrl) { + case CTRL_SYNC: + return RES_OK; + case GET_SECTOR_SIZE: + *((WORD *)buff) = MMCSD_BLOCK_SIZE; + return RES_OK; +#if _USE_ERASE + case CTRL_ERASE_SECTOR: + mmcErase(&MMCD1, *((DWORD *)buff), *((DWORD *)buff + 1)); + return RES_OK; +#endif + default: + return RES_PARERR; + } +#else + case SDC: + switch (ctrl) { + case CTRL_SYNC: + return RES_OK; + case GET_SECTOR_COUNT: + *((DWORD *)buff) = mmcsdGetCardCapacity(&SDCD1); + return RES_OK; + case GET_SECTOR_SIZE: + *((WORD *)buff) = MMCSD_BLOCK_SIZE; + return RES_OK; + case GET_BLOCK_SIZE: + *((DWORD *)buff) = 256; /* 512b blocks in one erase block */ + return RES_OK; +#if _USE_ERASE + case CTRL_ERASE_SECTOR: + sdcErase(&SDCD1, *((DWORD *)buff), *((DWORD *)buff + 1)); + return RES_OK; +#endif + default: + return RES_PARERR; + } +#endif + } + return RES_PARERR; +} + +DWORD get_fattime(void) { +#if HAL_USE_RTC + return rtcGetTimeFat(&RTCD1); +#else + return ((uint32_t)0 | (1 << 16)) | (1 << 21); /* wrong but valid time */ +#endif +} + + + diff --git a/src/gfile/fatfs/src/chibios_fatfs_syscall.c b/src/gfile/fatfs/src/chibios_fatfs_syscall.c new file mode 100644 index 00000000..a42cbcff --- /dev/null +++ b/src/gfile/fatfs/src/chibios_fatfs_syscall.c @@ -0,0 +1,84 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/*------------------------------------------------------------------------*/ +/* Sample code of OS dependent controls for FatFs R0.08b */ +/* (C)ChaN, 2011 */ +/*------------------------------------------------------------------------*/ + +#include "ch.h" +#include "ff.h" + +#if _FS_REENTRANT +/*------------------------------------------------------------------------*/ +/* Static array of Synchronization Objects */ +/*------------------------------------------------------------------------*/ +static Semaphore ff_sem[_VOLUMES]; + +/*------------------------------------------------------------------------*/ +/* Create a Synchronization Object */ +/*------------------------------------------------------------------------*/ +int ff_cre_syncobj(BYTE vol, _SYNC_t *sobj) { + + *sobj = &ff_sem[vol]; + chSemInit(*sobj, 1); + return TRUE; +} + +/*------------------------------------------------------------------------*/ +/* Delete a Synchronization Object */ +/*------------------------------------------------------------------------*/ +int ff_del_syncobj(_SYNC_t sobj) { + + chSemReset(sobj, 0); + return TRUE; +} + +/*------------------------------------------------------------------------*/ +/* Request Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +int ff_req_grant(_SYNC_t sobj) { + + msg_t msg = chSemWaitTimeout(sobj, (systime_t)_FS_TIMEOUT); + return msg == RDY_OK; +} + +/*------------------------------------------------------------------------*/ +/* Release Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +void ff_rel_grant(_SYNC_t sobj) { + + chSemSignal(sobj); +} +#endif /* _FS_REENTRANT */ + +#if _USE_LFN == 3 /* LFN with a working buffer on the heap */ +/*------------------------------------------------------------------------*/ +/* Allocate a memory block */ +/*------------------------------------------------------------------------*/ +void *ff_memalloc(UINT size) { + + return chHeapAlloc(NULL, size); +} + +/*------------------------------------------------------------------------*/ +/* Free a memory block */ +/*------------------------------------------------------------------------*/ +void ff_memfree(void *mblock) { + + chHeapFree(mblock); +} +#endif /* _USE_LFN == 3 */ diff --git a/src/gfile/gfile.c b/src/gfile/gfile.c index e8ba37c6..7af27cbf 100644 --- a/src/gfile/gfile.c +++ b/src/gfile/gfile.c @@ -97,7 +97,7 @@ GFILE *gfileStdErr; /******************************************************** * The FAT file-system VMT ********************************************************/ -#ifndef GFILE_NEED_FATFS +#if GFILE_NEED_FATFS #include "src/gfile/inc_fatfs.c" #endif diff --git a/src/gfile/inc_fatfs.c b/src/gfile/inc_fatfs.c index 0a8a4cd1..c90b6c30 100644 --- a/src/gfile/inc_fatfs.c +++ b/src/gfile/inc_fatfs.c @@ -9,6 +9,9 @@ * This file is included by src/gfile/gfile.c */ +#include "ff.h" +#include "ffconf.h" + /******************************************************** * The FAT file-system VMT ********************************************************/ @@ -45,58 +48,124 @@ static const GFILEVMT FsFatFSVMT = { #undef GFILE_CHAINHEAD #define GFILE_CHAINHEAD &FsFatFSVMT +static void _flags2mode(GFILE* f, BYTE* mode) +{ + *mode = 0; + + if (f->flags & GFILEFLG_MUSTEXIST) + *mode |= FA_READ; + else if (f->flags & GFILEFLG_APPEND) + *mode |= 0; /* ToDO */ + else + *mode |= FA_WRITE; + + /* ToDo - Complete */ +} + static bool_t fatfsDel(const char* fname) { + FRESULT ferr; + ferr = f_unlink( (const TCHAR*)fname ); + if (ferr != FR_OK) + return FALSE; + + return TRUE; } static bool_t fatfsExists(const char* fname) { + (void)fname; + /* ToDo */ + + return TRUE; } static long int fatfsFileSize(const char* fname) { + FRESULT ferr; + FILINFO fno; + ferr = f_stat( (const TCHAR*)fname, &fno ); + if (ferr != FR_OK) + return 0; + + return (long int)fno.fsize; } static bool_t fatfsRename(const char* oldname, const char* newname) { + FRESULT ferr; + ferr = f_rename( (const TCHAR*)oldname, (const TCHAR*)newname ); + if (ferr != FR_OK) + return FALSE; + + return TRUE; } static bool_t fatfsOpen(GFILE* f, const char* fname) { + FIL* fd = 0; + BYTE mode; + FRESULT ferr; + _flags2mode(f, &mode); + + ferr = f_open(fd, fname, mode); + if (ferr != FR_OK) + return FALSE; + + f->obj = (void*)fd; + + return TRUE; } static void fatfsClose(GFILE* f) { - + f_close( (FIL*)f->obj ); } static int fatfsRead(GFILE* f, void* buf, int size) { + int br; + f_read( (FIL*)f->obj, buf, size, (UINT*)&br); + + return br; } static int fatfsWrite(GFILE* f, const void* buf, int size) { + int wr; + f_write( (FIL*)f->obj, buf, size, (UINT*)&wr); + + return wr; } static bool_t fatfsSetPos(GFILE* f, long int pos) { + FRESULT ferr; + ferr = f_lseek( (FIL*)f->obj, (DWORD)pos ); + if (ferr != FR_OK) + return FALSE; + + return TRUE; } static long int fatfsGetSize(GFILE* f) { - + return (long int)f_tell( (FIL*)f->obj ); } static bool_t fatfsEOF(GFILE* f) { - + if ( f_eof( (FIL*)f->obj ) != 0) + return TRUE; + else + return FALSE; } diff --git a/src/gfile/sys_make.mk b/src/gfile/sys_make.mk index 381bd6f6..034fb977 100644 --- a/src/gfile/sys_make.mk +++ b/src/gfile/sys_make.mk @@ -1 +1,4 @@ +include $(GFXLIB)/src/gfile/fatfs/fatfs.mk + GFXSRC += $(GFXLIB)/src/gfile/gfile.c +