mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			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
							parent
							
								
									b8e31c8156
								
							
						
					
					
						commit
						840c77793b
					
				| 
						 | 
				
			
			@ -27,7 +27,7 @@ using namespace utest::v1;
 | 
			
		|||
 * stack tracking statistics are enabled. If this is the case, build dummy
 | 
			
		||||
 * 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 HEAP_BLOCK_DEVICE_TEST_01         test_read_write
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ void test_read_write() {
 | 
			
		|||
    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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -78,7 +78,7 @@ static control_t heap_block_device_test_dummy()
 | 
			
		|||
    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
 | 
			
		||||
utest::v1::status_t test_setup(const size_t number_of_cases) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bd_size_t BlockDevice::get_write_size()
 | 
			
		||||
bd_size_t BlockDevice::get_write_size() const
 | 
			
		||||
{
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    return (
 | 
			
		||||
        is_aligned(addr, get_read_size()) &&
 | 
			
		||||
        is_aligned(size, get_read_size()) &&
 | 
			
		||||
        addr + size <= this->size());
 | 
			
		||||
               is_aligned(addr, get_read_size()) &&
 | 
			
		||||
               is_aligned(size, get_read_size()) &&
 | 
			
		||||
               addr + size <= this->size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool BlockDevice::is_valid_erase(bd_addr_t addr, bd_size_t size)
 | 
			
		||||
{
 | 
			
		||||
    return (
 | 
			
		||||
        is_aligned(addr, get_erase_size()) &&
 | 
			
		||||
        is_aligned(size, get_erase_size()) &&
 | 
			
		||||
        addr + size <= this->size());
 | 
			
		||||
               is_aligned(addr, get_erase_size()) &&
 | 
			
		||||
               is_aligned(size, get_erase_size()) &&
 | 
			
		||||
               addr + size <= this->size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool BlockDevice::is_valid_program(bd_addr_t addr, bd_size_t size)
 | 
			
		||||
{
 | 
			
		||||
    return (
 | 
			
		||||
        is_aligned(addr, get_program_size()) &&
 | 
			
		||||
        is_aligned(size, get_program_size()) &&
 | 
			
		||||
        addr + size <= this->size());
 | 
			
		||||
               is_aligned(addr, get_program_size()) &&
 | 
			
		||||
               is_aligned(size, get_program_size()) &&
 | 
			
		||||
               addr + size <= this->size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,8 @@ typedef uint64_t bd_size_t;
 | 
			
		|||
 | 
			
		||||
/** A hardware device capable of writing and reading blocks
 | 
			
		||||
 */
 | 
			
		||||
class BlockDevice {
 | 
			
		||||
class BlockDevice
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /** Lifetime of a block device
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +120,7 @@ public:
 | 
			
		|||
     *
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			@ -127,21 +128,21 @@ public:
 | 
			
		|||
     *  @note Must be a multiple of the read size, this is
 | 
			
		||||
     *  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
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Size of a programable block in bytes
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Size of a eraseable block in bytes
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ bd_error_t ChainingBlockDevice::init()
 | 
			
		|||
    _erase_size = 0;
 | 
			
		||||
    _size = 0;
 | 
			
		||||
 | 
			
		||||
    // Initialize children block devices, find all sizes and 
 | 
			
		||||
    // Initialize children block devices, find all sizes and
 | 
			
		||||
    // assert that block sizes are similar. We can't do this in
 | 
			
		||||
    // the constructor since some block devices may need to be
 | 
			
		||||
    // initialized before they know their block size/count
 | 
			
		||||
| 
						 | 
				
			
			@ -183,17 +183,17 @@ bd_error_t ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bd_size_t ChainingBlockDevice::get_read_size()
 | 
			
		||||
bd_size_t ChainingBlockDevice::get_read_size() const
 | 
			
		||||
{
 | 
			
		||||
    return _read_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bd_size_t ChainingBlockDevice::get_program_size()
 | 
			
		||||
bd_size_t ChainingBlockDevice::get_program_size() const
 | 
			
		||||
{
 | 
			
		||||
    return _program_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bd_size_t ChainingBlockDevice::get_erase_size()
 | 
			
		||||
bd_size_t ChainingBlockDevice::get_erase_size() const
 | 
			
		||||
{
 | 
			
		||||
    return _erase_size;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,8 @@
 | 
			
		|||
 *  BlockDevice *bds[] = {&mem1, &mem2};
 | 
			
		||||
 *  ChainingBlockDevice chainmem(bds);
 | 
			
		||||
 */
 | 
			
		||||
class ChainingBlockDevice : public BlockDevice {
 | 
			
		||||
class ChainingBlockDevice : public BlockDevice
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /** Lifetime of the memory block device
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +63,8 @@ public:
 | 
			
		|||
    template <size_t Size>
 | 
			
		||||
    ChainingBlockDevice(BlockDevice *(&bds)[Size])
 | 
			
		||||
        : _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
 | 
			
		||||
| 
						 | 
				
			
			@ -118,21 +120,21 @@ public:
 | 
			
		|||
     *
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Size of a programable block in bytes
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Size of a eraseable block in bytes
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,7 @@ HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block)
 | 
			
		|||
    MBED_ASSERT(_count * _erase_size == size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HeapBlockDevice::HeapBlockDevice(bd_size_t size,
 | 
			
		||||
        bd_size_t read, bd_size_t program, bd_size_t erase)
 | 
			
		||||
HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase)
 | 
			
		||||
    : _read_size(read), _program_size(program), _erase_size(erase)
 | 
			
		||||
    , _count(size / erase), _blocks(0)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -63,17 +62,17 @@ bd_error_t HeapBlockDevice::deinit()
 | 
			
		|||
    return BD_ERROR_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bd_size_t HeapBlockDevice::get_read_size()
 | 
			
		||||
bd_size_t HeapBlockDevice::get_read_size() const
 | 
			
		||||
{
 | 
			
		||||
    return _read_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bd_size_t HeapBlockDevice::get_program_size()
 | 
			
		||||
bd_size_t HeapBlockDevice::get_program_size() const
 | 
			
		||||
{
 | 
			
		||||
    return _program_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bd_size_t HeapBlockDevice::get_erase_size()
 | 
			
		||||
bd_size_t HeapBlockDevice::get_erase_size() const
 | 
			
		||||
{
 | 
			
		||||
    return _erase_size;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +141,6 @@ bd_error_t HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size)
 | 
			
		|||
        return BD_ERROR_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
    while (size > 0) {
 | 
			
		||||
        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;
 | 
			
		||||
        size -= _erase_size;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,8 @@
 | 
			
		|||
 *     bd.deinit();
 | 
			
		||||
 * }
 | 
			
		||||
 */
 | 
			
		||||
class HeapBlockDevice : public BlockDevice {
 | 
			
		||||
class HeapBlockDevice : public BlockDevice
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /** Lifetime of the memory block device
 | 
			
		||||
| 
						 | 
				
			
			@ -100,19 +101,19 @@ public:
 | 
			
		|||
     *
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,17 +104,17 @@ bd_error_t SlicingBlockDevice::erase(bd_addr_t addr, bd_size_t 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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bd_size_t SlicingBlockDevice::get_program_size()
 | 
			
		||||
bd_size_t SlicingBlockDevice::get_program_size() const
 | 
			
		||||
{
 | 
			
		||||
    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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,8 @@
 | 
			
		|||
 *  // Create a block device that maps to the middle 32 blocks
 | 
			
		||||
 *  SlicingBlockDevice slice3(&mem, 16*512, -16*512);
 | 
			
		||||
 */
 | 
			
		||||
class SlicingBlockDevice : public BlockDevice {
 | 
			
		||||
class SlicingBlockDevice : public BlockDevice
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /** Lifetime of the memory block device
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			@ -117,21 +118,21 @@ public:
 | 
			
		|||
     *
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Size of a programable block in bytes
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
     *  @return         Size of a eraseable block in bytes
 | 
			
		||||
     *  @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
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,11 +26,13 @@
 | 
			
		|||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATDirHandle::closedir() {
 | 
			
		||||
int FATDirHandle::closedir()
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    FRESULT retval = f_closedir(&dir);
 | 
			
		||||
    fat_filesystem_set_errno(retval);
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +41,8 @@ int FATDirHandle::closedir() {
 | 
			
		|||
    return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct dirent *FATDirHandle::readdir() {
 | 
			
		||||
struct dirent *FATDirHandle::readdir()
 | 
			
		||||
{
 | 
			
		||||
    FILINFO finfo;
 | 
			
		||||
 | 
			
		||||
    lock();
 | 
			
		||||
| 
						 | 
				
			
			@ -76,14 +79,16 @@ struct dirent *FATDirHandle::readdir() {
 | 
			
		|||
#endif /* _USE_LFN */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FATDirHandle::rewinddir() {
 | 
			
		||||
void FATDirHandle::rewinddir()
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    dir.index = 0;
 | 
			
		||||
    fat_filesystem_set_errno(FR_OK);
 | 
			
		||||
    unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
off_t FATDirHandle::telldir() {
 | 
			
		||||
off_t FATDirHandle::telldir()
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    off_t offset = dir.index;
 | 
			
		||||
    fat_filesystem_set_errno(FR_OK);
 | 
			
		||||
| 
						 | 
				
			
			@ -91,18 +96,21 @@ off_t FATDirHandle::telldir() {
 | 
			
		|||
    return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FATDirHandle::seekdir(off_t location) {
 | 
			
		||||
void FATDirHandle::seekdir(off_t location)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    dir.index = location;
 | 
			
		||||
    fat_filesystem_set_errno(FR_OK);
 | 
			
		||||
    unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FATDirHandle::lock() {
 | 
			
		||||
void FATDirHandle::lock()
 | 
			
		||||
{
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FATDirHandle::unlock() {
 | 
			
		||||
void FATDirHandle::unlock()
 | 
			
		||||
{
 | 
			
		||||
    _mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,9 +27,10 @@
 | 
			
		|||
 | 
			
		||||
using namespace mbed;
 | 
			
		||||
 | 
			
		||||
class FATDirHandle : public DirHandle {
 | 
			
		||||
class FATDirHandle : public DirHandle
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
public:
 | 
			
		||||
    FATDirHandle(const FATFS_DIR &the_dir, PlatformMutex * mutex);
 | 
			
		||||
    virtual int closedir();
 | 
			
		||||
    virtual struct dirent *readdir();
 | 
			
		||||
| 
						 | 
				
			
			@ -37,14 +38,14 @@ class FATDirHandle : public DirHandle {
 | 
			
		|||
    virtual off_t telldir();
 | 
			
		||||
    virtual void seekdir(off_t location);
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    virtual void lock();
 | 
			
		||||
    virtual void unlock();
 | 
			
		||||
 | 
			
		||||
    PlatformMutex * _mutex;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
private:
 | 
			
		||||
    FATFS_DIR dir;
 | 
			
		||||
    struct dirent cur_entry;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,11 +26,13 @@
 | 
			
		|||
#include "FATFileHandle.h"
 | 
			
		||||
#include "FATMisc.h"
 | 
			
		||||
 | 
			
		||||
FATFileHandle::FATFileHandle(FIL fh, PlatformMutex * mutex): _mutex(mutex) {
 | 
			
		||||
FATFileHandle::FATFileHandle(FIL fh, PlatformMutex * mutex): _mutex(mutex)
 | 
			
		||||
{
 | 
			
		||||
    _fh = fh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileHandle::close() {
 | 
			
		||||
int FATFileHandle::close()
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    FRESULT retval = f_close(&_fh);
 | 
			
		||||
    fat_filesystem_set_errno(retval);
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +41,8 @@ int FATFileHandle::close() {
 | 
			
		|||
    return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t FATFileHandle::write(const void* buffer, size_t length) {
 | 
			
		||||
ssize_t FATFileHandle::write(const void* buffer, size_t length)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    UINT 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t FATFileHandle::read(void* buffer, size_t length) {
 | 
			
		||||
ssize_t FATFileHandle::read(void* buffer, size_t length)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    debug_if(FFS_DBG, "read(%d)\n", length);
 | 
			
		||||
    UINT n;
 | 
			
		||||
| 
						 | 
				
			
			@ -68,12 +72,14 @@ ssize_t FATFileHandle::read(void* buffer, size_t length) {
 | 
			
		|||
    return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileHandle::isatty() {
 | 
			
		||||
int FATFileHandle::isatty()
 | 
			
		||||
{
 | 
			
		||||
    fat_filesystem_set_errno(FR_OK);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
off_t FATFileHandle::lseek(off_t position, int whence) {
 | 
			
		||||
off_t FATFileHandle::lseek(off_t position, int whence)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    if (whence == SEEK_END) {
 | 
			
		||||
        position += _fh.fsize;
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +99,8 @@ off_t FATFileHandle::lseek(off_t position, int whence) {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileHandle::fsync() {
 | 
			
		||||
int FATFileHandle::fsync()
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    FRESULT res = f_sync(&_fh);
 | 
			
		||||
    fat_filesystem_set_errno(res);
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +113,8 @@ int FATFileHandle::fsync() {
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
off_t FATFileHandle::flen() {
 | 
			
		||||
off_t FATFileHandle::flen()
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    off_t size = _fh.fsize;
 | 
			
		||||
    fat_filesystem_set_errno(FR_OK);
 | 
			
		||||
| 
						 | 
				
			
			@ -114,10 +122,12 @@ off_t FATFileHandle::flen() {
 | 
			
		|||
    return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FATFileHandle::lock() {
 | 
			
		||||
void FATFileHandle::lock()
 | 
			
		||||
{
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FATFileHandle::unlock() {
 | 
			
		||||
void FATFileHandle::unlock()
 | 
			
		||||
{
 | 
			
		||||
    _mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,8 @@
 | 
			
		|||
 | 
			
		||||
using namespace mbed;
 | 
			
		||||
 | 
			
		||||
class FATFileHandle : public FileHandle {
 | 
			
		||||
class FATFileHandle : public FileHandle
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    FATFileHandle(FIL fh, PlatformMutex * mutex);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,44 +62,50 @@ static SingletonPtr<PlatformMutex> _ffs_mutex;
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
// FAT driver functions
 | 
			
		||||
DWORD get_fattime(void) {
 | 
			
		||||
DWORD get_fattime(void)
 | 
			
		||||
{
 | 
			
		||||
    time_t rawtime;
 | 
			
		||||
    time(&rawtime);
 | 
			
		||||
    struct tm *ptm = localtime(&rawtime);
 | 
			
		||||
    return (DWORD)(ptm->tm_year - 80) << 25
 | 
			
		||||
         | (DWORD)(ptm->tm_mon + 1  ) << 21
 | 
			
		||||
         | (DWORD)(ptm->tm_mday     ) << 16
 | 
			
		||||
         | (DWORD)(ptm->tm_hour     ) << 11
 | 
			
		||||
         | (DWORD)(ptm->tm_min      ) << 5
 | 
			
		||||
         | (DWORD)(ptm->tm_sec/2    );
 | 
			
		||||
           | (DWORD)(ptm->tm_mon + 1  ) << 21
 | 
			
		||||
           | (DWORD)(ptm->tm_mday     ) << 16
 | 
			
		||||
           | (DWORD)(ptm->tm_hour     ) << 11
 | 
			
		||||
           | (DWORD)(ptm->tm_min      ) << 5
 | 
			
		||||
           | (DWORD)(ptm->tm_sec/2    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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);
 | 
			
		||||
    return RES_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DSTATUS disk_initialize(BYTE pdrv) {
 | 
			
		||||
DSTATUS disk_initialize(BYTE pdrv)
 | 
			
		||||
{
 | 
			
		||||
    debug_if(FFS_DBG, "disk_initialize on pdrv [%d]\n", pdrv);
 | 
			
		||||
    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);
 | 
			
		||||
    bd_size_t ssize = _ffs[pdrv]->get_write_size();
 | 
			
		||||
    int err = _ffs[pdrv]->read(buff, sector*ssize, count*ssize);
 | 
			
		||||
    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);
 | 
			
		||||
    bd_size_t ssize = _ffs[pdrv]->get_write_size();
 | 
			
		||||
    int err = _ffs[pdrv]->write(buff, sector*ssize, count*ssize);
 | 
			
		||||
    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);
 | 
			
		||||
    switch (cmd) {
 | 
			
		||||
        case CTRL_SYNC:
 | 
			
		||||
| 
						 | 
				
			
			@ -134,18 +140,21 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
 | 
			
		|||
 | 
			
		||||
// Filesystem implementation (See FATFilySystem.h)
 | 
			
		||||
FATFileSystem::FATFileSystem(const char *n, BlockDevice *bd)
 | 
			
		||||
        : FileSystemLike(n), _id(-1) {
 | 
			
		||||
    : FileSystemLike(n), _id(-1)
 | 
			
		||||
{
 | 
			
		||||
    if (bd) {
 | 
			
		||||
        mount(bd);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FATFileSystem::~FATFileSystem() {
 | 
			
		||||
FATFileSystem::~FATFileSystem()
 | 
			
		||||
{
 | 
			
		||||
    // nop if unmounted
 | 
			
		||||
    unmount();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileSystem::mount(BlockDevice *bd, bool force) {
 | 
			
		||||
int FATFileSystem::mount(BlockDevice *bd, bool force)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    if (_id != -1) {
 | 
			
		||||
        unlock();
 | 
			
		||||
| 
						 | 
				
			
			@ -170,7 +179,8 @@ int FATFileSystem::mount(BlockDevice *bd, bool force) {
 | 
			
		|||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileSystem::unmount() {
 | 
			
		||||
int FATFileSystem::unmount()
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    if (_id == -1) {
 | 
			
		||||
        unlock();
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +195,8 @@ int FATFileSystem::unmount() {
 | 
			
		|||
    return res == 0 ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileSystem::sync() {
 | 
			
		||||
int FATFileSystem::sync()
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    if (_id == -1) {
 | 
			
		||||
        unlock();
 | 
			
		||||
| 
						 | 
				
			
			@ -200,7 +211,8 @@ int FATFileSystem::sync() {
 | 
			
		|||
 | 
			
		||||
/* See http://elm-chan.org/fsw/ff/en/mkfs.html for details of f_mkfs() and
 | 
			
		||||
 * associated arguments. */
 | 
			
		||||
int FATFileSystem::format(BlockDevice *bd, int allocation_unit) {
 | 
			
		||||
int FATFileSystem::format(BlockDevice *bd, int allocation_unit)
 | 
			
		||||
{
 | 
			
		||||
    FATFileSystem fs("");
 | 
			
		||||
    int err = fs.mount(bd, false);
 | 
			
		||||
    if (err) {
 | 
			
		||||
| 
						 | 
				
			
			@ -220,7 +232,8 @@ int FATFileSystem::format(BlockDevice *bd, int allocation_unit) {
 | 
			
		|||
    return res == 0 ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileHandle *FATFileSystem::open(const char* name, int flags) {
 | 
			
		||||
FileHandle *FATFileSystem::open(const char* name, int flags)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", name, getName(), _fsid);
 | 
			
		||||
    char n[64];
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +272,8 @@ FileHandle *FATFileSystem::open(const char* name, int flags) {
 | 
			
		|||
    return handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileSystem::remove(const char *filename) {
 | 
			
		||||
int FATFileSystem::remove(const char *filename)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    FRESULT res = f_unlink(filename);
 | 
			
		||||
    fat_filesystem_set_errno(res);
 | 
			
		||||
| 
						 | 
				
			
			@ -272,7 +286,8 @@ int FATFileSystem::remove(const char *filename) {
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileSystem::rename(const char *oldname, const char *newname) {
 | 
			
		||||
int FATFileSystem::rename(const char *oldname, const char *newname)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    FRESULT res = f_rename(oldname, newname);
 | 
			
		||||
    fat_filesystem_set_errno(res);
 | 
			
		||||
| 
						 | 
				
			
			@ -285,7 +300,8 @@ int FATFileSystem::rename(const char *oldname, const char *newname) {
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DirHandle *FATFileSystem::opendir(const char *name) {
 | 
			
		||||
DirHandle *FATFileSystem::opendir(const char *name)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    FATFS_DIR dir;
 | 
			
		||||
    FRESULT res = f_opendir(&dir, name);
 | 
			
		||||
| 
						 | 
				
			
			@ -299,7 +315,8 @@ DirHandle *FATFileSystem::opendir(const char *name) {
 | 
			
		|||
    return handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileSystem::mkdir(const char *name, mode_t mode) {
 | 
			
		||||
int FATFileSystem::mkdir(const char *name, mode_t mode)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    FRESULT res = f_mkdir(name);
 | 
			
		||||
    fat_filesystem_set_errno(res);
 | 
			
		||||
| 
						 | 
				
			
			@ -307,7 +324,8 @@ int FATFileSystem::mkdir(const char *name, mode_t mode) {
 | 
			
		|||
    return res == 0 ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FATFileSystem::stat(const char *name, struct stat *st) {
 | 
			
		||||
int FATFileSystem::stat(const char *name, struct stat *st)
 | 
			
		||||
{
 | 
			
		||||
    lock();
 | 
			
		||||
    FILINFO f;
 | 
			
		||||
    memset(&f, 0, sizeof(f));
 | 
			
		||||
| 
						 | 
				
			
			@ -319,24 +337,27 @@ int FATFileSystem::stat(const char *name, struct stat *st) {
 | 
			
		|||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* ARMCC doesnt support stat(), and these symbols are not defined by the toolchain. */
 | 
			
		||||
#ifdef TOOLCHAIN_GCC
 | 
			
		||||
    /* ARMCC doesnt support stat(), and these symbols are not defined by the toolchain.
 | 
			
		||||
     * Build only for GCC_ARM compiler. */
 | 
			
		||||
#if defined(__GNU__)
 | 
			
		||||
    st->st_size = f.fsize;
 | 
			
		||||
    st->st_mode = 0;
 | 
			
		||||
    st->st_mode |= (f.fattrib & AM_DIR) ? S_IFDIR : S_IFREG;
 | 
			
		||||
    st->st_mode |= (f.fattrib & AM_RDO) ?
 | 
			
		||||
        (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) :
 | 
			
		||||
        (S_IRWXU | S_IRWXG | S_IRWXO);
 | 
			
		||||
#endif /* TOOLCHAIN_GCC */
 | 
			
		||||
                   (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) :
 | 
			
		||||
                   (S_IRWXU | S_IRWXG | S_IRWXO);
 | 
			
		||||
#endif /* __GNU__ */
 | 
			
		||||
    unlock();
 | 
			
		||||
    return res == 0 ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FATFileSystem::lock() {
 | 
			
		||||
void FATFileSystem::lock()
 | 
			
		||||
{
 | 
			
		||||
    _ffs_mutex->lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FATFileSystem::unlock() {
 | 
			
		||||
void FATFileSystem::unlock()
 | 
			
		||||
{
 | 
			
		||||
    _ffs_mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,13 +32,14 @@
 | 
			
		|||
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:
 | 
			
		||||
    FATFileSystem(const char* n, BlockDevice *bd = NULL);
 | 
			
		||||
    virtual ~FATFileSystem();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief   Mounts the filesystem
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +50,7 @@ public:
 | 
			
		|||
     *   Flag to underlying filesystem to force the mounting of the filesystem.
 | 
			
		||||
     */
 | 
			
		||||
    virtual int mount(BlockDevice *bd, bool force = true);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Unmounts the filesystem
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +60,7 @@ public:
 | 
			
		|||
     * Flush any underlying transactions
 | 
			
		||||
     */
 | 
			
		||||
    virtual int sync();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief   Formats a logical drive, FDISK partitioning rule.
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			@ -81,22 +82,22 @@ public:
 | 
			
		|||
     * Opens a file on the filesystem
 | 
			
		||||
     */
 | 
			
		||||
    virtual FileHandle *open(const char* name, int flags);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Removes a file path
 | 
			
		||||
     */
 | 
			
		||||
    virtual int remove(const char *filename);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Renames a file
 | 
			
		||||
     */
 | 
			
		||||
    virtual int rename(const char *oldname, const char *newname);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Opens a directory on the filesystem
 | 
			
		||||
     */
 | 
			
		||||
    virtual DirHandle *opendir(const char *name);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a directory path
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			@ -106,12 +107,34 @@ public:
 | 
			
		|||
     * Store information about file in stat structure
 | 
			
		||||
     */
 | 
			
		||||
    virtual int stat(const char *name, struct stat *st);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    FATFS _fs; // Work area (file system object) for logical drive
 | 
			
		||||
    char _fsid[2];
 | 
			
		||||
    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 unlock();
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,12 +22,6 @@
 | 
			
		|||
#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)
 | 
			
		||||
{
 | 
			
		||||
    switch(res) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +22,15 @@
 | 
			
		|||
 | 
			
		||||
#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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,66 +11,71 @@
 | 
			
		|||
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:
 | 
			
		||||
    
 | 
			
		||||
        // 2000 sectors, each 512 bytes (malloced as required)
 | 
			
		||||
        char *sectors[2000];
 | 
			
		||||
    
 | 
			
		||||
        MemFileSystem(const char* name) : FATFileSystem(name) {
 | 
			
		||||
            memset(sectors, 0, sizeof(sectors));
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        virtual ~MemFileSystem() {
 | 
			
		||||
            for(int i = 0; i < 2000; i++) {
 | 
			
		||||
                if(sectors[i]) {
 | 
			
		||||
                    free(sectors[i]);
 | 
			
		||||
                }
 | 
			
		||||
        memset(sectors, 0, sizeof(sectors));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
        virtual int disk_read(char *buffer, int sector) {
 | 
			
		||||
            if(sectors[sector] == 0) {
 | 
			
		||||
                // nothing allocated means sector is empty
 | 
			
		||||
                memset(buffer, 0, 512);
 | 
			
		||||
            } else {
 | 
			
		||||
                memcpy(buffer, sectors[sector], 512);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // read a sector in to the buffer, return 0 if ok
 | 
			
		||||
    virtual int disk_read(char *buffer, int sector)
 | 
			
		||||
    {
 | 
			
		||||
        if(sectors[sector] == 0) {
 | 
			
		||||
            // nothing allocated means sector is empty
 | 
			
		||||
            memset(buffer, 0, 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;
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        // 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;
 | 
			
		||||
        // else allocate a sector if needed, and write
 | 
			
		||||
        if(sectors[sector] == 0) {
 | 
			
		||||
            char *sec = (char*)malloc(512);
 | 
			
		||||
            if(sec==0) {
 | 
			
		||||
                return 1; // out of memory
 | 
			
		||||
            }
 | 
			
		||||
            // else allocate a sector if needed, and write
 | 
			
		||||
            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;
 | 
			
		||||
            sectors[sector] = sec;
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        // return the number of sectors
 | 
			
		||||
        virtual int disk_sectors() {
 | 
			
		||||
            return sizeof(sectors)/sizeof(sectors[0]);
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
    };
 | 
			
		||||
        memcpy(sectors[sector], buffer, 512);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // return the number of sectors
 | 
			
		||||
    virtual int disk_sectors()
 | 
			
		||||
    {
 | 
			
		||||
        return sizeof(sectors)/sizeof(sectors[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -422,7 +422,6 @@ extern "C" int _fstat(int fd, struct stat *st) {
 | 
			
		|||
        st->st_mode = S_IFCHR;
 | 
			
		||||
        return  0;
 | 
			
		||||
    }
 | 
			
		||||
    /* todo: 20170120 this should now be made to work as _stat() is implemented */
 | 
			
		||||
    errno = EBADF;
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,19 +14,19 @@
 | 
			
		|||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * 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
 | 
			
		||||
#define RETARGET_H
 | 
			
		||||
 | 
			
		||||
#if defined TOOLCHAIN_ARM_STD || defined TOOLCHAIN_IAR
 | 
			
		||||
/* The following are errno.h definitions not currently present in the ARMCC
 | 
			
		||||
 * errno.h. Note, ARMCC errno.h defines some symbols values differing from
 | 
			
		||||
 * GCC_ARM/IAR/standard POSIX definitions.Guard against this and future
 | 
			
		||||
 * changes by changing the symbol definition for filesystem use. */
 | 
			
		||||
#if defined(__ARMCC_VERSION) || defined(__ICCARM__)
 | 
			
		||||
/* The intent of this section is to unify the errno error values to match
 | 
			
		||||
 * the POSIX definitions for the GCC_ARM, ARMCC and IAR compilers. This is
 | 
			
		||||
 * necessary because the ARMCC/IAR errno.h, or sys/stat.h are missing some
 | 
			
		||||
 * 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
 | 
			
		||||
#undef ENOENT
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -106,6 +106,6 @@
 | 
			
		|||
#define     S_IWOTH 0000002 /* write 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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,9 +24,7 @@ from tools.settings import ROOT, BUILD_DIR
 | 
			
		|||
BUILD_DIR = getenv("MBED_BUILD_DIR") or BUILD_DIR
 | 
			
		||||
 | 
			
		||||
# Embedded Libraries Sources
 | 
			
		||||
FEATURES_DIR = join(ROOT, "features")  
 | 
			
		||||
LIB_DIR = join(FEATURES_DIR, "unsupported")  
 | 
			
		||||
 | 
			
		||||
LIB_DIR = join(ROOT, "features/unsupported")
 | 
			
		||||
 | 
			
		||||
TOOLS = join(ROOT, "tools")
 | 
			
		||||
TOOLS_DATA = join(TOOLS, "data")
 | 
			
		||||
| 
						 | 
				
			
			@ -78,12 +76,6 @@ ETH_LIBRARY = join(NET_LIBRARIES, "eth")
 | 
			
		|||
VODAFONE_LIBRARY = join(NET_LIBRARIES, "VodafoneUSBModem")
 | 
			
		||||
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 = join(LIB_DIR, "dsp")
 | 
			
		||||
DSP_CMSIS = join(DSP, "cmsis_dsp")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -216,13 +216,6 @@ TESTS = [
 | 
			
		|||
        "supported": DEFAULT_SUPPORT,
 | 
			
		||||
        "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",
 | 
			
		||||
        "source_dir": join(TEST_DIR, "mbed", "i2c_MMA7660"),
 | 
			
		||||
| 
						 | 
				
			
			@ -394,29 +387,6 @@ TESTS = [
 | 
			
		|||
        "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
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -538,12 +508,6 @@ TESTS = [
 | 
			
		|||
        "source_dir": join(TEST_DIR, "mbed", "dir"),
 | 
			
		||||
        "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",
 | 
			
		||||
        "source_dir": join(TEST_DIR, "mbed", "interruptin_2"),
 | 
			
		||||
| 
						 | 
				
			
			@ -853,7 +817,7 @@ TESTS = [
 | 
			
		|||
    {
 | 
			
		||||
        "id": "RTOS_9", "description": "SD File write-read",
 | 
			
		||||
        "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,
 | 
			
		||||
        "peripherals": ["SD"],
 | 
			
		||||
        "mcu": ["LPC1768", "LPC11U24", "LPC812", "KL25Z", "HEXIWEAR",
 | 
			
		||||
| 
						 | 
				
			
			@ -1092,7 +1056,7 @@ TESTS = [
 | 
			
		|||
    {
 | 
			
		||||
        "id": "EXAMPLE_2", "description": "FS + RTOS",
 | 
			
		||||
        "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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue