STORAGE: Pull request 3762 review feedback changes.

- Fixing code formatting errors with astyle tool.
- Replaced use of TOOLCHAIN_xxx macros with compiler emitted macros.
- Added const to BlockDevice::get_xxx_size() member functions.
- Added documentation for FAT filesystem thread support.
- Added documentation for fat_filesystem_set_errno().
- Added documentation clarifying the reasons for errno/stat symbol definitions in retarget.h.
- Removed FAT filesystem from mbed 2 testing.
- Fixed FATMisc.h Copyright (c) 2016 year to 2017 as its a new file.
- Removed #ifndef NDEBUG from HeapBlockDevice.cpp.
- Removed unnecessary todo comment in retarget.cpp.
pull/3762/head
Simon Hughes 2017-02-22 15:19:02 +00:00
parent b8e31c8156
commit 840c77793b
22 changed files with 254 additions and 225 deletions

View File

@ -27,7 +27,7 @@ using namespace utest::v1;
* stack tracking statistics are enabled. If this is the case, build dummy * stack tracking statistics are enabled. If this is the case, build dummy
* tests. * tests.
*/ */
#if ! defined(TOOLCHAIN_IAR) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) #if ! defined(__ICCARM__) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED)
#define BLOCK_SIZE 512 #define BLOCK_SIZE 512
#define HEAP_BLOCK_DEVICE_TEST_01 test_read_write #define HEAP_BLOCK_DEVICE_TEST_01 test_read_write
@ -64,7 +64,7 @@ void test_read_write() {
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
} }
#else /* ! defined(TOOLCHAIN_IAR) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */ #else /* ! defined(__ICCARM__) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */
#define HEAP_BLOCK_DEVICE_TEST_01 heap_block_device_test_dummy #define HEAP_BLOCK_DEVICE_TEST_01 heap_block_device_test_dummy
@ -78,7 +78,7 @@ static control_t heap_block_device_test_dummy()
return CaseNext; return CaseNext;
} }
#endif /* ! defined(TOOLCHAIN_IAR) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */ #endif /* ! defined(__ICCARM__) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */
// Test setup // Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) { utest::v1::status_t test_setup(const size_t number_of_cases) {

View File

@ -32,7 +32,7 @@ bd_error_t BlockDevice::write(const void *buffer, bd_addr_t addr, bd_size_t size
return program(buffer, addr, size); return program(buffer, addr, size);
} }
bd_size_t BlockDevice::get_write_size() bd_size_t BlockDevice::get_write_size() const
{ {
return get_erase_size(); return get_erase_size();
} }
@ -52,24 +52,24 @@ static bool is_aligned(uint64_t x, uint64_t alignment)
bool BlockDevice::is_valid_read(bd_addr_t addr, bd_size_t size) bool BlockDevice::is_valid_read(bd_addr_t addr, bd_size_t size)
{ {
return ( return (
is_aligned(addr, get_read_size()) && is_aligned(addr, get_read_size()) &&
is_aligned(size, get_read_size()) && is_aligned(size, get_read_size()) &&
addr + size <= this->size()); addr + size <= this->size());
} }
bool BlockDevice::is_valid_erase(bd_addr_t addr, bd_size_t size) bool BlockDevice::is_valid_erase(bd_addr_t addr, bd_size_t size)
{ {
return ( return (
is_aligned(addr, get_erase_size()) && is_aligned(addr, get_erase_size()) &&
is_aligned(size, get_erase_size()) && is_aligned(size, get_erase_size()) &&
addr + size <= this->size()); addr + size <= this->size());
} }
bool BlockDevice::is_valid_program(bd_addr_t addr, bd_size_t size) bool BlockDevice::is_valid_program(bd_addr_t addr, bd_size_t size)
{ {
return ( return (
is_aligned(addr, get_program_size()) && is_aligned(addr, get_program_size()) &&
is_aligned(size, get_program_size()) && is_aligned(size, get_program_size()) &&
addr + size <= this->size()); addr + size <= this->size());
} }

View File

@ -50,7 +50,8 @@ typedef uint64_t bd_size_t;
/** A hardware device capable of writing and reading blocks /** A hardware device capable of writing and reading blocks
*/ */
class BlockDevice { class BlockDevice
{
public: public:
/** Lifetime of a block device /** Lifetime of a block device
*/ */
@ -119,7 +120,7 @@ public:
* *
* @return Size of a readable block in bytes * @return Size of a readable block in bytes
*/ */
virtual bd_size_t get_read_size() = 0; virtual bd_size_t get_read_size() const = 0;
/** Get the size of a writeable block /** Get the size of a writeable block
* *
@ -127,21 +128,21 @@ public:
* @note Must be a multiple of the read size, this is * @note Must be a multiple of the read size, this is
* equivalent to the erase size of the device * equivalent to the erase size of the device
*/ */
virtual bd_size_t get_write_size(); virtual bd_size_t get_write_size() const;
/** Get the size of a programable block /** Get the size of a programable block
* *
* @return Size of a programable block in bytes * @return Size of a programable block in bytes
* @note Must be a multiple of the read size * @note Must be a multiple of the read size
*/ */
virtual bd_size_t get_program_size() = 0; virtual bd_size_t get_program_size() const = 0;
/** Get the size of a eraseable block /** Get the size of a eraseable block
* *
* @return Size of a eraseable block in bytes * @return Size of a eraseable block in bytes
* @note Must be a multiple of the program size * @note Must be a multiple of the program size
*/ */
virtual bd_size_t get_erase_size() = 0; virtual bd_size_t get_erase_size() const = 0;
/** Get the total size of the underlying device /** Get the total size of the underlying device
* *

View File

@ -183,17 +183,17 @@ bd_error_t ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
return 0; return 0;
} }
bd_size_t ChainingBlockDevice::get_read_size() bd_size_t ChainingBlockDevice::get_read_size() const
{ {
return _read_size; return _read_size;
} }
bd_size_t ChainingBlockDevice::get_program_size() bd_size_t ChainingBlockDevice::get_program_size() const
{ {
return _program_size; return _program_size;
} }
bd_size_t ChainingBlockDevice::get_erase_size() bd_size_t ChainingBlockDevice::get_erase_size() const
{ {
return _erase_size; return _erase_size;
} }

View File

@ -44,7 +44,8 @@
* BlockDevice *bds[] = {&mem1, &mem2}; * BlockDevice *bds[] = {&mem1, &mem2};
* ChainingBlockDevice chainmem(bds); * ChainingBlockDevice chainmem(bds);
*/ */
class ChainingBlockDevice : public BlockDevice { class ChainingBlockDevice : public BlockDevice
{
public: public:
/** Lifetime of the memory block device /** Lifetime of the memory block device
* *
@ -62,7 +63,8 @@ public:
template <size_t Size> template <size_t Size>
ChainingBlockDevice(BlockDevice *(&bds)[Size]) ChainingBlockDevice(BlockDevice *(&bds)[Size])
: _bds(bds), _bd_count(sizeof(bds) / sizeof(bds[0])) : _bds(bds), _bd_count(sizeof(bds) / sizeof(bds[0]))
, _read_size(0), _program_size(0), _erase_size(0), _size(0) { , _read_size(0), _program_size(0), _erase_size(0), _size(0)
{
} }
/** Lifetime of the memory block device /** Lifetime of the memory block device
@ -118,21 +120,21 @@ public:
* *
* @return Size of a readable block in bytes * @return Size of a readable block in bytes
*/ */
virtual bd_size_t get_read_size(); virtual bd_size_t get_read_size() const;
/** Get the size of a programable block /** Get the size of a programable block
* *
* @return Size of a programable block in bytes * @return Size of a programable block in bytes
* @note Must be a multiple of the read size * @note Must be a multiple of the read size
*/ */
virtual bd_size_t get_program_size(); virtual bd_size_t get_program_size() const;
/** Get the size of a eraseable block /** Get the size of a eraseable block
* *
* @return Size of a eraseable block in bytes * @return Size of a eraseable block in bytes
* @note Must be a multiple of the program size * @note Must be a multiple of the program size
*/ */
virtual bd_size_t get_erase_size(); virtual bd_size_t get_erase_size() const;
/** Get the total size of the underlying device /** Get the total size of the underlying device
* *

View File

@ -24,8 +24,7 @@ HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block)
MBED_ASSERT(_count * _erase_size == size); MBED_ASSERT(_count * _erase_size == size);
} }
HeapBlockDevice::HeapBlockDevice(bd_size_t size, HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase)
bd_size_t read, bd_size_t program, bd_size_t erase)
: _read_size(read), _program_size(program), _erase_size(erase) : _read_size(read), _program_size(program), _erase_size(erase)
, _count(size / erase), _blocks(0) , _count(size / erase), _blocks(0)
{ {
@ -63,17 +62,17 @@ bd_error_t HeapBlockDevice::deinit()
return BD_ERROR_OK; return BD_ERROR_OK;
} }
bd_size_t HeapBlockDevice::get_read_size() bd_size_t HeapBlockDevice::get_read_size() const
{ {
return _read_size; return _read_size;
} }
bd_size_t HeapBlockDevice::get_program_size() bd_size_t HeapBlockDevice::get_program_size() const
{ {
return _program_size; return _program_size;
} }
bd_size_t HeapBlockDevice::get_erase_size() bd_size_t HeapBlockDevice::get_erase_size() const
{ {
return _erase_size; return _erase_size;
} }
@ -142,7 +141,6 @@ bd_error_t HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size)
return BD_ERROR_PARAMETER; return BD_ERROR_PARAMETER;
} }
#ifndef NDEBUG
while (size > 0) { while (size > 0) {
bd_addr_t hi = addr / _erase_size; bd_addr_t hi = addr / _erase_size;
@ -153,7 +151,6 @@ bd_error_t HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size)
addr += _erase_size; addr += _erase_size;
size -= _erase_size; size -= _erase_size;
} }
#endif
return 0; return 0;
} }

View File

@ -45,7 +45,8 @@
* bd.deinit(); * bd.deinit();
* } * }
*/ */
class HeapBlockDevice : public BlockDevice { class HeapBlockDevice : public BlockDevice
{
public: public:
/** Lifetime of the memory block device /** Lifetime of the memory block device
@ -100,19 +101,19 @@ public:
* *
* @return Size of a readable block in bytes * @return Size of a readable block in bytes
*/ */
virtual bd_size_t get_read_size(); virtual bd_size_t get_read_size() const;
/** Get the size of a programable block /** Get the size of a programable block
* *
* @return Size of a programable block in bytes * @return Size of a programable block in bytes
*/ */
virtual bd_size_t get_program_size(); virtual bd_size_t get_program_size() const;
/** Get the size of a eraseable block /** Get the size of a eraseable block
* *
* @return Size of a eraseable block in bytes * @return Size of a eraseable block in bytes
*/ */
virtual bd_size_t get_erase_size(); virtual bd_size_t get_erase_size() const;
/** Get the total size of the underlying device /** Get the total size of the underlying device
* *

View File

@ -104,17 +104,17 @@ bd_error_t SlicingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
return _bd->erase(addr + _start, size); return _bd->erase(addr + _start, size);
} }
bd_size_t SlicingBlockDevice::get_read_size() bd_size_t SlicingBlockDevice::get_read_size() const
{ {
return _bd->get_read_size(); return _bd->get_read_size();
} }
bd_size_t SlicingBlockDevice::get_program_size() bd_size_t SlicingBlockDevice::get_program_size() const
{ {
return _bd->get_program_size(); return _bd->get_program_size();
} }
bd_size_t SlicingBlockDevice::get_erase_size() bd_size_t SlicingBlockDevice::get_erase_size() const
{ {
return _bd->get_erase_size(); return _bd->get_erase_size();
} }

View File

@ -45,7 +45,8 @@
* // Create a block device that maps to the middle 32 blocks * // Create a block device that maps to the middle 32 blocks
* SlicingBlockDevice slice3(&mem, 16*512, -16*512); * SlicingBlockDevice slice3(&mem, 16*512, -16*512);
*/ */
class SlicingBlockDevice : public BlockDevice { class SlicingBlockDevice : public BlockDevice
{
public: public:
/** Lifetime of the memory block device /** Lifetime of the memory block device
* *
@ -117,21 +118,21 @@ public:
* *
* @return Size of a readable block in bytes * @return Size of a readable block in bytes
*/ */
virtual bd_size_t get_read_size(); virtual bd_size_t get_read_size() const;
/** Get the size of a programable block /** Get the size of a programable block
* *
* @return Size of a programable block in bytes * @return Size of a programable block in bytes
* @note Must be a multiple of the read size * @note Must be a multiple of the read size
*/ */
virtual bd_size_t get_program_size(); virtual bd_size_t get_program_size() const;
/** Get the size of a eraseable block /** Get the size of a eraseable block
* *
* @return Size of a eraseable block in bytes * @return Size of a eraseable block in bytes
* @note Must be a multiple of the program size * @note Must be a multiple of the program size
*/ */
virtual bd_size_t get_erase_size(); virtual bd_size_t get_erase_size() const;
/** Get the total size of the underlying device /** Get the total size of the underlying device
* *

View File

@ -26,11 +26,13 @@
using namespace mbed; using namespace mbed;
FATDirHandle::FATDirHandle(const FATFS_DIR &the_dir, PlatformMutex * mutex): _mutex(mutex) { FATDirHandle::FATDirHandle(const FATFS_DIR &the_dir, PlatformMutex * mutex): _mutex(mutex)
{
dir = the_dir; dir = the_dir;
} }
int FATDirHandle::closedir() { int FATDirHandle::closedir()
{
lock(); lock();
FRESULT retval = f_closedir(&dir); FRESULT retval = f_closedir(&dir);
fat_filesystem_set_errno(retval); fat_filesystem_set_errno(retval);
@ -39,7 +41,8 @@ int FATDirHandle::closedir() {
return retval; return retval;
} }
struct dirent *FATDirHandle::readdir() { struct dirent *FATDirHandle::readdir()
{
FILINFO finfo; FILINFO finfo;
lock(); lock();
@ -76,14 +79,16 @@ struct dirent *FATDirHandle::readdir() {
#endif /* _USE_LFN */ #endif /* _USE_LFN */
} }
void FATDirHandle::rewinddir() { void FATDirHandle::rewinddir()
{
lock(); lock();
dir.index = 0; dir.index = 0;
fat_filesystem_set_errno(FR_OK); fat_filesystem_set_errno(FR_OK);
unlock(); unlock();
} }
off_t FATDirHandle::telldir() { off_t FATDirHandle::telldir()
{
lock(); lock();
off_t offset = dir.index; off_t offset = dir.index;
fat_filesystem_set_errno(FR_OK); fat_filesystem_set_errno(FR_OK);
@ -91,18 +96,21 @@ off_t FATDirHandle::telldir() {
return offset; return offset;
} }
void FATDirHandle::seekdir(off_t location) { void FATDirHandle::seekdir(off_t location)
{
lock(); lock();
dir.index = location; dir.index = location;
fat_filesystem_set_errno(FR_OK); fat_filesystem_set_errno(FR_OK);
unlock(); unlock();
} }
void FATDirHandle::lock() { void FATDirHandle::lock()
{
_mutex->lock(); _mutex->lock();
} }
void FATDirHandle::unlock() { void FATDirHandle::unlock()
{
_mutex->unlock(); _mutex->unlock();
} }

View File

@ -27,9 +27,10 @@
using namespace mbed; using namespace mbed;
class FATDirHandle : public DirHandle { class FATDirHandle : public DirHandle
{
public: public:
FATDirHandle(const FATFS_DIR &the_dir, PlatformMutex * mutex); FATDirHandle(const FATFS_DIR &the_dir, PlatformMutex * mutex);
virtual int closedir(); virtual int closedir();
virtual struct dirent *readdir(); virtual struct dirent *readdir();
@ -37,14 +38,14 @@ class FATDirHandle : public DirHandle {
virtual off_t telldir(); virtual off_t telldir();
virtual void seekdir(off_t location); virtual void seekdir(off_t location);
protected: protected:
virtual void lock(); virtual void lock();
virtual void unlock(); virtual void unlock();
PlatformMutex * _mutex; PlatformMutex * _mutex;
private: private:
FATFS_DIR dir; FATFS_DIR dir;
struct dirent cur_entry; struct dirent cur_entry;

View File

@ -26,11 +26,13 @@
#include "FATFileHandle.h" #include "FATFileHandle.h"
#include "FATMisc.h" #include "FATMisc.h"
FATFileHandle::FATFileHandle(FIL fh, PlatformMutex * mutex): _mutex(mutex) { FATFileHandle::FATFileHandle(FIL fh, PlatformMutex * mutex): _mutex(mutex)
{
_fh = fh; _fh = fh;
} }
int FATFileHandle::close() { int FATFileHandle::close()
{
lock(); lock();
FRESULT retval = f_close(&_fh); FRESULT retval = f_close(&_fh);
fat_filesystem_set_errno(retval); fat_filesystem_set_errno(retval);
@ -39,7 +41,8 @@ int FATFileHandle::close() {
return retval; return retval;
} }
ssize_t FATFileHandle::write(const void* buffer, size_t length) { ssize_t FATFileHandle::write(const void* buffer, size_t length)
{
lock(); lock();
UINT n; UINT n;
FRESULT res = f_write(&_fh, buffer, length, &n); FRESULT res = f_write(&_fh, buffer, length, &n);
@ -53,7 +56,8 @@ ssize_t FATFileHandle::write(const void* buffer, size_t length) {
return n; return n;
} }
ssize_t FATFileHandle::read(void* buffer, size_t length) { ssize_t FATFileHandle::read(void* buffer, size_t length)
{
lock(); lock();
debug_if(FFS_DBG, "read(%d)\n", length); debug_if(FFS_DBG, "read(%d)\n", length);
UINT n; UINT n;
@ -68,12 +72,14 @@ ssize_t FATFileHandle::read(void* buffer, size_t length) {
return n; return n;
} }
int FATFileHandle::isatty() { int FATFileHandle::isatty()
{
fat_filesystem_set_errno(FR_OK); fat_filesystem_set_errno(FR_OK);
return 0; return 0;
} }
off_t FATFileHandle::lseek(off_t position, int whence) { off_t FATFileHandle::lseek(off_t position, int whence)
{
lock(); lock();
if (whence == SEEK_END) { if (whence == SEEK_END) {
position += _fh.fsize; position += _fh.fsize;
@ -93,7 +99,8 @@ off_t FATFileHandle::lseek(off_t position, int whence) {
} }
} }
int FATFileHandle::fsync() { int FATFileHandle::fsync()
{
lock(); lock();
FRESULT res = f_sync(&_fh); FRESULT res = f_sync(&_fh);
fat_filesystem_set_errno(res); fat_filesystem_set_errno(res);
@ -106,7 +113,8 @@ int FATFileHandle::fsync() {
return 0; return 0;
} }
off_t FATFileHandle::flen() { off_t FATFileHandle::flen()
{
lock(); lock();
off_t size = _fh.fsize; off_t size = _fh.fsize;
fat_filesystem_set_errno(FR_OK); fat_filesystem_set_errno(FR_OK);
@ -114,10 +122,12 @@ off_t FATFileHandle::flen() {
return size; return size;
} }
void FATFileHandle::lock() { void FATFileHandle::lock()
{
_mutex->lock(); _mutex->lock();
} }
void FATFileHandle::unlock() { void FATFileHandle::unlock()
{
_mutex->unlock(); _mutex->unlock();
} }

View File

@ -27,7 +27,8 @@
using namespace mbed; using namespace mbed;
class FATFileHandle : public FileHandle { class FATFileHandle : public FileHandle
{
public: public:
FATFileHandle(FIL fh, PlatformMutex * mutex); FATFileHandle(FIL fh, PlatformMutex * mutex);

View File

@ -62,44 +62,50 @@ static SingletonPtr<PlatformMutex> _ffs_mutex;
// FAT driver functions // FAT driver functions
DWORD get_fattime(void) { DWORD get_fattime(void)
{
time_t rawtime; time_t rawtime;
time(&rawtime); time(&rawtime);
struct tm *ptm = localtime(&rawtime); struct tm *ptm = localtime(&rawtime);
return (DWORD)(ptm->tm_year - 80) << 25 return (DWORD)(ptm->tm_year - 80) << 25
| (DWORD)(ptm->tm_mon + 1 ) << 21 | (DWORD)(ptm->tm_mon + 1 ) << 21
| (DWORD)(ptm->tm_mday ) << 16 | (DWORD)(ptm->tm_mday ) << 16
| (DWORD)(ptm->tm_hour ) << 11 | (DWORD)(ptm->tm_hour ) << 11
| (DWORD)(ptm->tm_min ) << 5 | (DWORD)(ptm->tm_min ) << 5
| (DWORD)(ptm->tm_sec/2 ); | (DWORD)(ptm->tm_sec/2 );
} }
// Implementation of diskio functions (see ChaN/diskio.h) // Implementation of diskio functions (see ChaN/diskio.h)
DSTATUS disk_status(BYTE pdrv) { DSTATUS disk_status(BYTE pdrv)
{
debug_if(FFS_DBG, "disk_status on pdrv [%d]\n", pdrv); debug_if(FFS_DBG, "disk_status on pdrv [%d]\n", pdrv);
return RES_OK; return RES_OK;
} }
DSTATUS disk_initialize(BYTE pdrv) { DSTATUS disk_initialize(BYTE pdrv)
{
debug_if(FFS_DBG, "disk_initialize on pdrv [%d]\n", pdrv); debug_if(FFS_DBG, "disk_initialize on pdrv [%d]\n", pdrv);
return (DSTATUS)_ffs[pdrv]->init(); return (DSTATUS)_ffs[pdrv]->init();
} }
DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count) { DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
{
debug_if(FFS_DBG, "disk_read(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv); debug_if(FFS_DBG, "disk_read(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv);
bd_size_t ssize = _ffs[pdrv]->get_write_size(); bd_size_t ssize = _ffs[pdrv]->get_write_size();
int err = _ffs[pdrv]->read(buff, sector*ssize, count*ssize); int err = _ffs[pdrv]->read(buff, sector*ssize, count*ssize);
return err ? RES_PARERR : RES_OK; return err ? RES_PARERR : RES_OK;
} }
DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) { DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
{
debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv); debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv);
bd_size_t ssize = _ffs[pdrv]->get_write_size(); bd_size_t ssize = _ffs[pdrv]->get_write_size();
int err = _ffs[pdrv]->write(buff, sector*ssize, count*ssize); int err = _ffs[pdrv]->write(buff, sector*ssize, count*ssize);
return err ? RES_PARERR : RES_OK; return err ? RES_PARERR : RES_OK;
} }
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) { DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
{
debug_if(FFS_DBG, "disk_ioctl(%d)\n", cmd); debug_if(FFS_DBG, "disk_ioctl(%d)\n", cmd);
switch (cmd) { switch (cmd) {
case CTRL_SYNC: case CTRL_SYNC:
@ -134,18 +140,21 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
// Filesystem implementation (See FATFilySystem.h) // Filesystem implementation (See FATFilySystem.h)
FATFileSystem::FATFileSystem(const char *n, BlockDevice *bd) FATFileSystem::FATFileSystem(const char *n, BlockDevice *bd)
: FileSystemLike(n), _id(-1) { : FileSystemLike(n), _id(-1)
{
if (bd) { if (bd) {
mount(bd); mount(bd);
} }
} }
FATFileSystem::~FATFileSystem() { FATFileSystem::~FATFileSystem()
{
// nop if unmounted // nop if unmounted
unmount(); unmount();
} }
int FATFileSystem::mount(BlockDevice *bd, bool force) { int FATFileSystem::mount(BlockDevice *bd, bool force)
{
lock(); lock();
if (_id != -1) { if (_id != -1) {
unlock(); unlock();
@ -170,7 +179,8 @@ int FATFileSystem::mount(BlockDevice *bd, bool force) {
return -1; return -1;
} }
int FATFileSystem::unmount() { int FATFileSystem::unmount()
{
lock(); lock();
if (_id == -1) { if (_id == -1) {
unlock(); unlock();
@ -185,7 +195,8 @@ int FATFileSystem::unmount() {
return res == 0 ? 0 : -1; return res == 0 ? 0 : -1;
} }
int FATFileSystem::sync() { int FATFileSystem::sync()
{
lock(); lock();
if (_id == -1) { if (_id == -1) {
unlock(); unlock();
@ -200,7 +211,8 @@ int FATFileSystem::sync() {
/* See http://elm-chan.org/fsw/ff/en/mkfs.html for details of f_mkfs() and /* See http://elm-chan.org/fsw/ff/en/mkfs.html for details of f_mkfs() and
* associated arguments. */ * associated arguments. */
int FATFileSystem::format(BlockDevice *bd, int allocation_unit) { int FATFileSystem::format(BlockDevice *bd, int allocation_unit)
{
FATFileSystem fs(""); FATFileSystem fs("");
int err = fs.mount(bd, false); int err = fs.mount(bd, false);
if (err) { if (err) {
@ -220,7 +232,8 @@ int FATFileSystem::format(BlockDevice *bd, int allocation_unit) {
return res == 0 ? 0 : -1; return res == 0 ? 0 : -1;
} }
FileHandle *FATFileSystem::open(const char* name, int flags) { FileHandle *FATFileSystem::open(const char* name, int flags)
{
lock(); lock();
debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", name, getName(), _fsid); debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", name, getName(), _fsid);
char n[64]; char n[64];
@ -259,7 +272,8 @@ FileHandle *FATFileSystem::open(const char* name, int flags) {
return handle; return handle;
} }
int FATFileSystem::remove(const char *filename) { int FATFileSystem::remove(const char *filename)
{
lock(); lock();
FRESULT res = f_unlink(filename); FRESULT res = f_unlink(filename);
fat_filesystem_set_errno(res); fat_filesystem_set_errno(res);
@ -272,7 +286,8 @@ int FATFileSystem::remove(const char *filename) {
return 0; return 0;
} }
int FATFileSystem::rename(const char *oldname, const char *newname) { int FATFileSystem::rename(const char *oldname, const char *newname)
{
lock(); lock();
FRESULT res = f_rename(oldname, newname); FRESULT res = f_rename(oldname, newname);
fat_filesystem_set_errno(res); fat_filesystem_set_errno(res);
@ -285,7 +300,8 @@ int FATFileSystem::rename(const char *oldname, const char *newname) {
return 0; return 0;
} }
DirHandle *FATFileSystem::opendir(const char *name) { DirHandle *FATFileSystem::opendir(const char *name)
{
lock(); lock();
FATFS_DIR dir; FATFS_DIR dir;
FRESULT res = f_opendir(&dir, name); FRESULT res = f_opendir(&dir, name);
@ -299,7 +315,8 @@ DirHandle *FATFileSystem::opendir(const char *name) {
return handle; return handle;
} }
int FATFileSystem::mkdir(const char *name, mode_t mode) { int FATFileSystem::mkdir(const char *name, mode_t mode)
{
lock(); lock();
FRESULT res = f_mkdir(name); FRESULT res = f_mkdir(name);
fat_filesystem_set_errno(res); fat_filesystem_set_errno(res);
@ -307,7 +324,8 @@ int FATFileSystem::mkdir(const char *name, mode_t mode) {
return res == 0 ? 0 : -1; return res == 0 ? 0 : -1;
} }
int FATFileSystem::stat(const char *name, struct stat *st) { int FATFileSystem::stat(const char *name, struct stat *st)
{
lock(); lock();
FILINFO f; FILINFO f;
memset(&f, 0, sizeof(f)); memset(&f, 0, sizeof(f));
@ -319,24 +337,27 @@ int FATFileSystem::stat(const char *name, struct stat *st) {
return -1; return -1;
} }
/* ARMCC doesnt support stat(), and these symbols are not defined by the toolchain. */ /* ARMCC doesnt support stat(), and these symbols are not defined by the toolchain.
#ifdef TOOLCHAIN_GCC * Build only for GCC_ARM compiler. */
#if defined(__GNU__)
st->st_size = f.fsize; st->st_size = f.fsize;
st->st_mode = 0; st->st_mode = 0;
st->st_mode |= (f.fattrib & AM_DIR) ? S_IFDIR : S_IFREG; st->st_mode |= (f.fattrib & AM_DIR) ? S_IFDIR : S_IFREG;
st->st_mode |= (f.fattrib & AM_RDO) ? st->st_mode |= (f.fattrib & AM_RDO) ?
(S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) : (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) :
(S_IRWXU | S_IRWXG | S_IRWXO); (S_IRWXU | S_IRWXG | S_IRWXO);
#endif /* TOOLCHAIN_GCC */ #endif /* __GNU__ */
unlock(); unlock();
return res == 0 ? 0 : -1; return res == 0 ? 0 : -1;
} }
void FATFileSystem::lock() { void FATFileSystem::lock()
{
_ffs_mutex->lock(); _ffs_mutex->lock();
} }
void FATFileSystem::unlock() { void FATFileSystem::unlock()
{
_ffs_mutex->unlock(); _ffs_mutex->unlock();
} }

View File

@ -34,7 +34,8 @@ using namespace mbed;
/** /**
* FATFileSystem based on ChaN's Fat Filesystem library v0.8 * FATFileSystem based on ChaN's Fat Filesystem library v0.8
*/ */
class FATFileSystem : public FileSystemLike { class FATFileSystem : public FileSystemLike
{
public: public:
FATFileSystem(const char* n, BlockDevice *bd = NULL); FATFileSystem(const char* n, BlockDevice *bd = NULL);
virtual ~FATFileSystem(); virtual ~FATFileSystem();
@ -112,6 +113,28 @@ protected:
char _fsid[2]; char _fsid[2];
int _id; int _id;
/* Access to the underlying FAT filesystem implementation from multiple
* concurrent clients (i.e. threads) is serialised using a single
* platform mutex (_ffs_mutex) The implementation is therefore thread
* safe (but this requires further validation and testing).
* - The platform mutex _ffs_mutex is defined in the FileSystemLike
* implementation.
* - FileSystemLike uses the mutex to gain exclusive access to the
* underlying block device for mount()/unmount()/format()/sync()
* operations.
* - FileSystemLike::open() uses the mutex to serialise FATFileHandle
* object creation. The FATFileHandle constructor is passed a pointer
* to the platform mutex so file operations (e.g. read()/write()/flen()
* /fsync()) are serialised with the rest of the implementation.
* - FileSystemLike::opendir() uses the mutex to serialise FATDirHandle
* object creation. The FATDirHandle constructor is passed a pointer
* to the platform mutex so directory operations (e.g. readdir()/
* telldir()/rewinddir()/closedir()) are serialised with the rest
* of the implementation.
* - The platform mutex _ffs_mutex is taken/given using the lock()/unlock()
* methods defined below, and similar helper methods exist in the
* FATFileHandle and FATDirHandle classes.
*/
virtual void lock(); virtual void lock();
virtual void unlock(); virtual void unlock();
}; };

View File

@ -22,12 +22,6 @@
#include "platform/retarget.h" #include "platform/retarget.h"
/* @brief Set errno based on the error code returned from underlying filesystem
*
* @param res result returned from underlying filesystem
*
* @return No return value
*/
void fat_filesystem_set_errno(FRESULT res) void fat_filesystem_set_errno(FRESULT res)
{ {
switch(res) { switch(res) {

View File

@ -1,6 +1,6 @@
/* /*
* mbed Microcontroller Library * mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited * Copyright (c) 2006-2017 ARM Limited
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,6 +22,15 @@
#include "ff.h" #include "ff.h"
void fat_filesystem_set_errno(FRESULT res); /* @brief Set errno based on the error code returned from underlying FAT32 filesystem.
*
* @note Note that errno reporting is not thread safe as this is not supported
* by current versions of standard libraries.
*
* @param res result returned from underlying filesystem which is mapped to a
* suitable errno value.
*
* @return No return value
*/void fat_filesystem_set_errno(FRESULT res);
#endif /* FILESYSTEM_FAT_MISC_H */ #endif /* FILESYSTEM_FAT_MISC_H */

View File

@ -11,66 +11,71 @@
namespace mbed namespace mbed
{ {
class MemFileSystem : public FATFileSystem class MemFileSystem : public FATFileSystem
{
public:
// 2000 sectors, each 512 bytes (malloced as required)
char *sectors[2000];
MemFileSystem(const char* name) : FATFileSystem(name)
{ {
public: memset(sectors, 0, sizeof(sectors));
}
// 2000 sectors, each 512 bytes (malloced as required) virtual ~MemFileSystem()
char *sectors[2000]; {
for(int i = 0; i < 2000; i++) {
MemFileSystem(const char* name) : FATFileSystem(name) { if(sectors[i]) {
memset(sectors, 0, sizeof(sectors)); free(sectors[i]);
}
virtual ~MemFileSystem() {
for(int i = 0; i < 2000; i++) {
if(sectors[i]) {
free(sectors[i]);
}
} }
} }
}
// read a sector in to the buffer, return 0 if ok // read a sector in to the buffer, return 0 if ok
virtual int disk_read(char *buffer, int sector) { virtual int disk_read(char *buffer, int sector)
if(sectors[sector] == 0) { {
// nothing allocated means sector is empty if(sectors[sector] == 0) {
memset(buffer, 0, 512); // nothing allocated means sector is empty
} else { memset(buffer, 0, 512);
memcpy(buffer, sectors[sector], 512); } else {
memcpy(buffer, sectors[sector], 512);
}
return 0;
}
// write a sector from the buffer, return 0 if ok
virtual int disk_write(const char *buffer, int sector)
{
// if buffer is zero deallocate sector
char zero[512];
memset(zero, 0, 512);
if(memcmp(zero, buffer, 512)==0) {
if(sectors[sector] != 0) {
free(sectors[sector]);
sectors[sector] = 0;
} }
return 0; return 0;
} }
// else allocate a sector if needed, and write
// write a sector from the buffer, return 0 if ok if(sectors[sector] == 0) {
virtual int disk_write(const char *buffer, int sector) { char *sec = (char*)malloc(512);
// if buffer is zero deallocate sector if(sec==0) {
char zero[512]; return 1; // out of memory
memset(zero, 0, 512);
if(memcmp(zero, buffer, 512)==0) {
if(sectors[sector] != 0) {
free(sectors[sector]);
sectors[sector] = 0;
}
return 0;
} }
// else allocate a sector if needed, and write sectors[sector] = sec;
if(sectors[sector] == 0) {
char *sec = (char*)malloc(512);
if(sec==0) {
return 1; // out of memory
}
sectors[sector] = sec;
}
memcpy(sectors[sector], buffer, 512);
return 0;
} }
memcpy(sectors[sector], buffer, 512);
return 0;
}
// return the number of sectors // return the number of sectors
virtual int disk_sectors() { virtual int disk_sectors()
return sizeof(sectors)/sizeof(sectors[0]); {
} return sizeof(sectors)/sizeof(sectors[0]);
}
}; };
} }

View File

@ -422,7 +422,6 @@ extern "C" int _fstat(int fd, struct stat *st) {
st->st_mode = S_IFCHR; st->st_mode = S_IFCHR;
return 0; return 0;
} }
/* todo: 20170120 this should now be made to work as _stat() is implemented */
errno = EBADF; errno = EBADF;
return -1; return -1;
} }

View File

@ -14,19 +14,19 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* This file contains symbols used by the implementation that are not present
* in the armcc errno.h, or sys/stat.h. These are used in for the POSIX
* filesystem API to return errno codes, for example.
*/ */
#ifndef RETARGET_H #ifndef RETARGET_H
#define RETARGET_H #define RETARGET_H
#if defined TOOLCHAIN_ARM_STD || defined TOOLCHAIN_IAR #if defined(__ARMCC_VERSION) || defined(__ICCARM__)
/* The following are errno.h definitions not currently present in the ARMCC /* The intent of this section is to unify the errno error values to match
* errno.h. Note, ARMCC errno.h defines some symbols values differing from * the POSIX definitions for the GCC_ARM, ARMCC and IAR compilers. This is
* GCC_ARM/IAR/standard POSIX definitions.Guard against this and future * necessary because the ARMCC/IAR errno.h, or sys/stat.h are missing some
* changes by changing the symbol definition for filesystem use. */ * symbol definitions used by the POSIX filesystem API to return errno codes.
* Note also that ARMCC errno.h defines some symbol values differently from
* the GCC_ARM/IAR/standard POSIX definitions. The definitions guard against
* this and future changes by changing the symbol definition as shown below. */
#ifdef ENOENT #ifdef ENOENT
#undef ENOENT #undef ENOENT
#endif #endif
@ -106,6 +106,6 @@
#define S_IWOTH 0000002 /* write permission, other */ #define S_IWOTH 0000002 /* write permission, other */
#define S_IXOTH 0000001/* execute/search permission, other */ #define S_IXOTH 0000001/* execute/search permission, other */
#endif /* TOOLCHAIN_ARM_STD || defined TOOLCHAIN_IAR */ #endif /* defined(__ARMCC_VERSION) || defined(__ICCARM__) */
#endif /* RETARGET_H */ #endif /* RETARGET_H */

View File

@ -24,9 +24,7 @@ from tools.settings import ROOT, BUILD_DIR
BUILD_DIR = getenv("MBED_BUILD_DIR") or BUILD_DIR BUILD_DIR = getenv("MBED_BUILD_DIR") or BUILD_DIR
# Embedded Libraries Sources # Embedded Libraries Sources
FEATURES_DIR = join(ROOT, "features") LIB_DIR = join(ROOT, "features/unsupported")
LIB_DIR = join(FEATURES_DIR, "unsupported")
TOOLS = join(ROOT, "tools") TOOLS = join(ROOT, "tools")
TOOLS_DATA = join(TOOLS, "data") TOOLS_DATA = join(TOOLS, "data")
@ -78,12 +76,6 @@ ETH_LIBRARY = join(NET_LIBRARIES, "eth")
VODAFONE_LIBRARY = join(NET_LIBRARIES, "VodafoneUSBModem") VODAFONE_LIBRARY = join(NET_LIBRARIES, "VodafoneUSBModem")
UBLOX_LIBRARY = join(NET_LIBRARIES, "UbloxUSBModem") UBLOX_LIBRARY = join(NET_LIBRARIES, "UbloxUSBModem")
# FS
FS_PATH = join(FEATURES_DIR, "filesystem")
FAT_FS = join(FS_PATH, "fat")
SD_FS = join(FS_PATH, "sd")
FS_LIBRARY = join(BUILD_DIR, "fat")
# DSP # DSP
DSP = join(LIB_DIR, "dsp") DSP = join(LIB_DIR, "dsp")
DSP_CMSIS = join(DSP, "cmsis_dsp") DSP_CMSIS = join(DSP, "cmsis_dsp")

View File

@ -216,13 +216,6 @@ TESTS = [
"supported": DEFAULT_SUPPORT, "supported": DEFAULT_SUPPORT,
"automated": True, "automated": True,
}, },
{
"id": "MBED_A12", "description": "SD File System",
"source_dir": join(TEST_DIR, "mbed", "sd"),
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, FS_LIBRARY],
"automated": True,
"peripherals": ["SD"]
},
{ {
"id": "MBED_A13", "description": "I2C MMA7660 accelerometer", "id": "MBED_A13", "description": "I2C MMA7660 accelerometer",
"source_dir": join(TEST_DIR, "mbed", "i2c_MMA7660"), "source_dir": join(TEST_DIR, "mbed", "i2c_MMA7660"),
@ -394,29 +387,6 @@ TESTS = [
"dependencies": [MBED_LIBRARIES] "dependencies": [MBED_LIBRARIES]
}, },
# performance related tests
{
"id": "PERF_1", "description": "SD Stdio R/W Speed",
"source_dir": join(TEST_DIR, "mbed", "sd_perf_stdio"),
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, FS_LIBRARY],
"automated": True,
"peripherals": ["SD"]
},
{
"id": "PERF_2", "description": "SD FileHandle R/W Speed",
"source_dir": join(TEST_DIR, "mbed", "sd_perf_fhandle"),
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, FS_LIBRARY],
"automated": True,
"peripherals": ["SD"]
},
{
"id": "PERF_3", "description": "SD FatFS R/W Speed",
"source_dir": join(TEST_DIR, "mbed", "sd_perf_fatfs"),
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, FS_LIBRARY],
"automated": True,
"peripherals": ["SD"]
},
# Not automated MBED tests # Not automated MBED tests
{ {
@ -538,12 +508,6 @@ TESTS = [
"source_dir": join(TEST_DIR, "mbed", "dir"), "source_dir": join(TEST_DIR, "mbed", "dir"),
"dependencies": [MBED_LIBRARIES], "dependencies": [MBED_LIBRARIES],
}, },
{
"id": "MBED_19", "description": "SD FS Directory",
"source_dir": join(TEST_DIR, "mbed", "dir_sd"),
"dependencies": [MBED_LIBRARIES, FS_LIBRARY],
"peripherals": ["SD"]
},
{ {
"id": "MBED_20", "description": "InterruptIn 2", "id": "MBED_20", "description": "InterruptIn 2",
"source_dir": join(TEST_DIR, "mbed", "interruptin_2"), "source_dir": join(TEST_DIR, "mbed", "interruptin_2"),
@ -853,7 +817,7 @@ TESTS = [
{ {
"id": "RTOS_9", "description": "SD File write-read", "id": "RTOS_9", "description": "SD File write-read",
"source_dir": join(TEST_DIR, "rtos", "mbed", "file"), "source_dir": join(TEST_DIR, "rtos", "mbed", "file"),
"dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB, FS_LIBRARY], "dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB],
"automated": True, "automated": True,
"peripherals": ["SD"], "peripherals": ["SD"],
"mcu": ["LPC1768", "LPC11U24", "LPC812", "KL25Z", "HEXIWEAR", "mcu": ["LPC1768", "LPC11U24", "LPC812", "KL25Z", "HEXIWEAR",
@ -1092,7 +1056,7 @@ TESTS = [
{ {
"id": "EXAMPLE_2", "description": "FS + RTOS", "id": "EXAMPLE_2", "description": "FS + RTOS",
"source_dir": join(TEST_DIR, "mbed", "fs"), "source_dir": join(TEST_DIR, "mbed", "fs"),
"dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB, FS_LIBRARY], "dependencies": [MBED_LIBRARIES, RTOS_LIBRARIES, TEST_MBED_LIB],
}, },
# CPPUTEST Library provides Unit testing Framework # CPPUTEST Library provides Unit testing Framework