Line 18... |
Line 18... |
* MediaBlockRead() //low level read
|
* MediaBlockRead() //low level read
|
* FileOpen() //open next directory
|
* FileOpen() //open next directory
|
* OS_fwrite() //write file entry into directory
|
* OS_fwrite() //write file entry into directory
|
* BlockRead() //flush changes to directory
|
* BlockRead() //flush changes to directory
|
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
#ifndef WIN32
|
#ifdef WIN32
|
#include "rtos.h"
|
|
#else
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
typedef unsigned int uint32;
|
#define _LIBC
|
typedef unsigned short uint16;
|
|
typedef unsigned char uint8;
|
|
#endif
|
#endif
|
|
#include "rtos.h"
|
|
|
#define BLOCK_SIZE 512
|
#define BLOCK_SIZE 512
|
#define FILE_NAME_SIZE 40
|
#define FILE_NAME_SIZE 40
|
#define FULL_NAME_SIZE 128
|
#define FULL_NAME_SIZE 128
|
#define BLOCK_MALLOC 0x0
|
#define BLOCK_MALLOC 0x0
|
Line 71... |
Line 68... |
OS_Block_t *block;
|
OS_Block_t *block;
|
OS_Block_t *blockLocal; //local copy for flash or disk file system
|
OS_Block_t *blockLocal; //local copy for flash or disk file system
|
};
|
};
|
|
|
static OS_FileEntry_t rootFileEntry;
|
static OS_FileEntry_t rootFileEntry;
|
|
static OS_Mutex_t *mutexFilesys;
|
|
|
// Public prototypes
|
// Public prototypes
|
#ifndef _FILESYS_
|
#ifndef _FILESYS_
|
typedef struct OS_FILE_s OS_FILE;
|
typedef struct OS_FILE_s OS_FILE;
|
#endif
|
#endif
|
Line 87... |
Line 85... |
int OS_fdir(OS_FILE *dir, char name[64]);
|
int OS_fdir(OS_FILE *dir, char name[64]);
|
void OS_fdelete(char *name);
|
void OS_fdelete(char *name);
|
|
|
|
|
/***************** Media Functions Start ***********************/
|
/***************** Media Functions Start ***********************/
|
|
#ifdef INCLUDE_FLASH
|
|
#define FLASH_BASE 1024*128
|
|
#define FLASH_BLOCKS 1024*1024*16/BLOCK_SIZE
|
|
#define FLASH_OFFSET (FLASH_BASE+FLASH_BLOCKS/8*2)/BLOCK_SIZE
|
|
static unsigned char FlashBlockEmpty[FLASH_BLOCKS/8];
|
|
static unsigned char FlashBlockUsed[FLASH_BLOCKS/8];
|
|
static int FlashOffset;
|
|
|
|
|
|
//Free unused flash blocks
|
|
static int MediaBlockCleanup(void)
|
|
{
|
|
int i, j, k, count=0;
|
|
unsigned char *buf;
|
|
|
|
printf("FlashCleanup\n");
|
|
buf = (unsigned char*)malloc(1024*128);
|
|
if(buf == NULL)
|
|
return 0;
|
|
for(j = 1; j < 128; ++j)
|
|
{
|
|
FlashRead((uint16*)buf, 1024*128*j, 1024*128);
|
|
if(j == 1)
|
|
{
|
|
for(i = 0; i < FLASH_BLOCKS/8; ++i)
|
|
FlashBlockEmpty[i] |= ~FlashBlockUsed[i];
|
|
memcpy(buf, FlashBlockEmpty, sizeof(FlashBlockEmpty));
|
|
memset(FlashBlockUsed, 0xff, sizeof(FlashBlockUsed));
|
|
memset(buf+sizeof(FlashBlockEmpty), 0xff, sizeof(FlashBlockUsed));
|
|
}
|
|
//Erase empty blocks
|
|
for(k = 0; k < 256; ++k)
|
|
{
|
|
i = j*256 + k;
|
|
if(FlashBlockEmpty[i >> 3] & (1 << (i & 7)))
|
|
{
|
|
memset(buf + BLOCK_SIZE*k, 0xff, BLOCK_SIZE);
|
|
++count;
|
|
}
|
|
}
|
|
FlashErase(1024*128*j);
|
|
FlashWrite((uint16*)buf, 1024*128*j, 1024*128);
|
|
}
|
|
free(buf);
|
|
return count;
|
|
}
|
|
|
|
|
|
int MediaBlockInit(void)
|
|
{
|
|
FlashRead((uint16*)FlashBlockEmpty, FLASH_BASE, sizeof(FlashBlockEmpty));
|
|
FlashRead((uint16*)FlashBlockUsed, FLASH_BASE+4096, sizeof(FlashBlockUsed));
|
|
FlashOffset = FLASH_OFFSET;
|
|
return FlashBlockEmpty[FlashOffset >> 3] & (1 << (FlashOffset & 7));
|
|
}
|
|
#endif
|
|
|
|
|
static uint32 MediaBlockMalloc(OS_FILE *file)
|
static uint32 MediaBlockMalloc(OS_FILE *file)
|
{
|
{
|
|
int i, j;
|
|
(void)i; (void)j;
|
|
|
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
|
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
|
return (uint32)malloc(file->fileEntry.blockSize);
|
return (uint32)malloc(file->fileEntry.blockSize);
|
else
|
#ifdef INCLUDE_FLASH
|
return (uint32)malloc(file->fileEntry.blockSize); //TODO
|
//Find empty flash block
|
|
for(i = FlashOffset; i < FLASH_BLOCKS; ++i)
|
|
{
|
|
if(FlashBlockEmpty[i >> 3] & (1 << (i & 7)))
|
|
{
|
|
FlashOffset = i + 1;
|
|
FlashBlockEmpty[i >> 3] &= ~(1 << (i & 7));
|
|
j = i >> 3;
|
|
j &= ~1;
|
|
FlashWrite((uint16*)(FlashBlockEmpty + j), FLASH_BASE + j, 2);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
i = MediaBlockCleanup();
|
|
if(i == 0)
|
|
return 0;
|
|
FlashOffset = FLASH_OFFSET;
|
|
return MediaBlockMalloc(file);
|
|
#else
|
|
return 0;
|
|
#endif
|
}
|
}
|
|
|
|
|
static void MediaBlockFree(OS_FILE *file, uint32 blockIndex)
|
static void MediaBlockFree(OS_FILE *file, uint32 blockIndex)
|
{
|
{
|
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
|
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
|
free((void*)blockIndex);
|
free((void*)blockIndex);
|
|
#ifdef INCLUDE_FLASH
|
else
|
else
|
free((void*)blockIndex); //TODO
|
{
|
|
int i=blockIndex, j;
|
|
FlashBlockUsed[i >> 3] &= ~(1 << (i & 7));
|
|
j = i >> 3;
|
|
j &= ~1;
|
|
FlashWrite((uint16*)(FlashBlockUsed + j), FLASH_BASE + sizeof(FlashBlockEmpty) + j, 2);
|
|
}
|
|
#endif
|
}
|
}
|
|
|
|
|
static void MediaBlockRead(OS_FILE *file, uint32 blockIndex)
|
static void MediaBlockRead(OS_FILE *file, uint32 blockIndex)
|
{
|
{
|
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
|
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
|
file->block = (OS_Block_t*)blockIndex;
|
file->block = (OS_Block_t*)blockIndex;
|
|
#ifdef INCLUDE_FLASH
|
else
|
else
|
{
|
{
|
if(file->blockLocal == NULL)
|
if(file->blockLocal == NULL)
|
file->blockLocal = (OS_Block_t*)malloc(file->fileEntry.blockSize);
|
file->blockLocal = (OS_Block_t*)malloc(BLOCK_SIZE);
|
file->block = file->blockLocal;
|
file->block = file->blockLocal;
|
memcpy(file->block, (void*)blockIndex, file->fileEntry.blockSize); //TODO
|
FlashRead((uint16*)file->block, blockIndex << 9, BLOCK_SIZE);
|
}
|
}
|
|
#endif
|
}
|
}
|
|
|
|
|
static void MediaBlockWrite(OS_FILE *file)
|
static void MediaBlockWrite(OS_FILE *file, uint32 blockIndex)
|
{
|
{
|
|
(void)file;
|
|
(void)blockIndex;
|
|
#ifdef INCLUDE_FLASH
|
if(file->fileEntry.mediaType != FILE_MEDIA_RAM)
|
if(file->fileEntry.mediaType != FILE_MEDIA_RAM)
|
memcpy((void*)file->blockIndex, file->block, file->fileEntry.blockSize); //TODO
|
FlashWrite((uint16*)file->block, blockIndex << 9, BLOCK_SIZE);
|
|
#endif
|
}
|
}
|
|
|
/***************** Media Functions End *************************/
|
/***************** Media Functions End *************************/
|
|
|
// Get the next block and write the old block if it was modified
|
// Get the next block and write the old block if it was modified
|
static void BlockRead(OS_FILE *file, uint32 blockIndex)
|
static void BlockRead(OS_FILE *file, uint32 blockIndex)
|
{
|
{
|
uint32 blockIndexSave = blockIndex;
|
uint32 blockIndexSave = blockIndex;
|
|
|
|
OS_MutexPend(mutexFilesys);
|
if(blockIndex == BLOCK_MALLOC)
|
if(blockIndex == BLOCK_MALLOC)
|
{
|
{
|
// Get a new block
|
// Get a new block
|
blockIndex = MediaBlockMalloc(file);
|
blockIndex = MediaBlockMalloc(file);
|
if(blockIndex == 0)
|
if(blockIndex == 0)
|
Line 147... |
Line 243... |
}
|
}
|
}
|
}
|
if(file->block && file->blockModified)
|
if(file->block && file->blockModified)
|
{
|
{
|
// Write block back to flash or disk
|
// Write block back to flash or disk
|
MediaBlockWrite(file);
|
MediaBlockWrite(file, file->blockIndex);
|
file->blockModified = 0;
|
file->blockModified = 0;
|
}
|
}
|
if(blockIndex == BLOCK_EOF)
|
if(blockIndex == BLOCK_EOF)
|
|
{
|
|
OS_MutexPost(mutexFilesys);
|
return;
|
return;
|
|
}
|
file->blockIndex = blockIndex;
|
file->blockIndex = blockIndex;
|
file->blockOffset = 0;
|
file->blockOffset = 0;
|
MediaBlockRead(file, blockIndex);
|
MediaBlockRead(file, blockIndex);
|
if(blockIndexSave == BLOCK_MALLOC)
|
if(blockIndexSave == BLOCK_MALLOC)
|
{
|
{
|
memset(file->block, 0xff, file->fileEntry.blockSize);
|
memset(file->block, 0xff, file->fileEntry.blockSize);
|
file->blockModified = 1;
|
file->blockModified = 1;
|
}
|
}
|
|
OS_MutexPost(mutexFilesys);
|
}
|
}
|
|
|
|
|
int OS_fread(void *buffer, int size, int count, OS_FILE *file)
|
int OS_fread(void *buffer, int size, int count, OS_FILE *file)
|
{
|
{
|
Line 194... |
Line 294... |
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file)
|
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file)
|
{
|
{
|
int items, bytes;
|
int items, bytes;
|
uint8 *buf = (uint8*)buffer;
|
uint8 *buf = (uint8*)buffer;
|
|
|
|
OS_MutexPend(mutexFilesys);
|
file->blockModified = 1;
|
file->blockModified = 1;
|
for(items = 0; items < count; ++items)
|
for(items = 0; items < count; ++items)
|
{
|
{
|
for(bytes = 0; bytes < size; ++bytes)
|
for(bytes = 0; bytes < size; ++bytes)
|
{
|
{
|
Line 220... |
Line 321... |
}
|
}
|
file->blockModified = 1;
|
file->blockModified = 1;
|
file->fileModified = 1;
|
file->fileModified = 1;
|
if(file->fileOffset > file->fileEntry.length)
|
if(file->fileOffset > file->fileEntry.length)
|
file->fileEntry.length = file->fileOffset;
|
file->fileEntry.length = file->fileOffset;
|
|
OS_MutexPost(mutexFilesys);
|
return items;
|
return items;
|
}
|
}
|
|
|
|
|
int OS_fseek(OS_FILE *file, int offset, int mode)
|
int OS_fseek(OS_FILE *file, int offset, int mode)
|
Line 371... |
Line 473... |
int rc;
|
int rc;
|
|
|
if(rootFileEntry.blockIndex == 0)
|
if(rootFileEntry.blockIndex == 0)
|
{
|
{
|
// Mount file system
|
// Mount file system
|
|
mutexFilesys = OS_MutexCreate("filesys");
|
memset(&dir, 0, sizeof(OS_FILE));
|
memset(&dir, 0, sizeof(OS_FILE));
|
dir.fileEntry.blockSize = BLOCK_SIZE;
|
dir.fileEntry.blockSize = BLOCK_SIZE;
|
//dir.fileEntry.mediaType = FILE_MEDIA_FLASH; //Test flash
|
//dir.fileEntry.mediaType = FILE_MEDIA_FLASH; //Test flash
|
BlockRead(&dir, BLOCK_MALLOC);
|
BlockRead(&dir, BLOCK_MALLOC);
|
strcpy(rootFileEntry.name, "/");
|
strcpy(rootFileEntry.name, "/");
|
rootFileEntry.mediaType = dir.fileEntry.mediaType;
|
rootFileEntry.mediaType = dir.fileEntry.mediaType;
|
rootFileEntry.blockIndex = dir.blockIndex;
|
rootFileEntry.blockIndex = dir.blockIndex;
|
rootFileEntry.blockSize = dir.fileEntry.blockSize;
|
rootFileEntry.blockSize = dir.fileEntry.blockSize;
|
rootFileEntry.isDirectory = 1;
|
rootFileEntry.isDirectory = 1;
|
BlockRead(&dir, BLOCK_EOF); //Flush data
|
BlockRead(&dir, BLOCK_EOF); //Flush data
|
|
#ifdef INCLUDE_FLASH
|
|
file = OS_fopen("flash", "w+");
|
|
if(file == NULL)
|
|
return NULL;
|
|
file->fileEntry.isDirectory = 1;
|
|
file->fileEntry.mediaType = FILE_MEDIA_FLASH;
|
|
file->blockLocal = file->block;
|
|
file->block = NULL;
|
|
rc = MediaBlockInit();
|
|
if(rc == 1)
|
|
BlockRead(file, BLOCK_MALLOC);
|
|
else
|
|
BlockRead(file, FLASH_OFFSET);
|
|
file->fileEntry.blockIndex = file->blockIndex;
|
|
OS_fclose(file);
|
|
#endif
|
}
|
}
|
|
|
file = (OS_FILE*)malloc(sizeof(OS_FILE));
|
file = (OS_FILE*)malloc(sizeof(OS_FILE));
|
if(file == NULL)
|
if(file == NULL)
|
return NULL;
|
return NULL;
|
|
OS_MutexPend(mutexFilesys);
|
if(name[0] == 0 || strcmp(name, "/") == 0)
|
if(name[0] == 0 || strcmp(name, "/") == 0)
|
{
|
{
|
FileOpen(file, NULL, NULL);
|
FileOpen(file, NULL, NULL);
|
|
OS_MutexPost(mutexFilesys);
|
return file;
|
return file;
|
}
|
}
|
if(strcmp(mode, "w") == 0)
|
if(strcmp(mode, "w") == 0)
|
OS_fdelete(name);
|
OS_fdelete(name);
|
rc = FileFindRecursive(&dir, name, &fileEntry, filename);
|
rc = FileFindRecursive(&dir, name, &fileEntry, filename);
|
if(dir.blockLocal)
|
if(dir.blockLocal)
|
free(dir.blockLocal);
|
free(dir.blockLocal);
|
if(rc == -2 || (rc && mode[0] == 'r'))
|
if(rc == -2 || (rc && mode[0] == 'r'))
|
{
|
{
|
free(file);
|
free(file);
|
|
OS_MutexPost(mutexFilesys);
|
return NULL;
|
return NULL;
|
}
|
}
|
rc = FileOpen(file, filename, &fileEntry); //Open file
|
rc = FileOpen(file, filename, &fileEntry); //Open file
|
file->fullname[0] = 0;
|
file->fullname[0] = 0;
|
strncat(file->fullname, name, FULL_NAME_SIZE);
|
strncat(file->fullname, name, FULL_NAME_SIZE);
|
|
OS_MutexPost(mutexFilesys);
|
return file;
|
return file;
|
}
|
}
|
|
|
|
|
void OS_fclose(OS_FILE *file)
|
void OS_fclose(OS_FILE *file)
|
Line 418... |
Line 541... |
int rc;
|
int rc;
|
|
|
if(file->fileModified)
|
if(file->fileModified)
|
{
|
{
|
// Write file->fileEntry into parent directory
|
// Write file->fileEntry into parent directory
|
|
OS_MutexPend(mutexFilesys);
|
BlockRead(file, BLOCK_EOF);
|
BlockRead(file, BLOCK_EOF);
|
rc = FileFindRecursive(&dir, file->fullname, &fileEntry, filename);
|
rc = FileFindRecursive(&dir, file->fullname, &fileEntry, filename);
|
if(file->fileEntry.mediaType == FILE_MEDIA_FLASH && rc == 0)
|
if(file->fileEntry.mediaType == FILE_MEDIA_FLASH && rc == 0)
|
{
|
{
|
// Invalidate old entry and add new entry at the end
|
// Invalidate old entry and add new entry at the end
|
Line 431... |
Line 555... |
}
|
}
|
OS_fwrite(&file->fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
|
OS_fwrite(&file->fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
|
BlockRead(&dir, BLOCK_EOF); //flush data
|
BlockRead(&dir, BLOCK_EOF); //flush data
|
if(dir.blockLocal)
|
if(dir.blockLocal)
|
free(dir.blockLocal);
|
free(dir.blockLocal);
|
|
OS_MutexPost(mutexFilesys);
|
}
|
}
|
if(file->blockLocal)
|
if(file->blockLocal)
|
free(file->blockLocal);
|
free(file->blockLocal);
|
free(file);
|
free(file);
|
}
|
}
|
Line 458... |
Line 583... |
OS_FileEntry_t fileEntry;
|
OS_FileEntry_t fileEntry;
|
int rc;
|
int rc;
|
uint32 blockIndex;
|
uint32 blockIndex;
|
char filename[FILE_NAME_SIZE]; //Name without directories
|
char filename[FILE_NAME_SIZE]; //Name without directories
|
|
|
|
OS_MutexPend(mutexFilesys);
|
rc = FileFindRecursive(&dir, name, &fileEntry, filename);
|
rc = FileFindRecursive(&dir, name, &fileEntry, filename);
|
if(rc == 0)
|
if(rc == 0)
|
{
|
{
|
FileOpen(&file, NULL, &fileEntry);
|
FileOpen(&file, NULL, &fileEntry);
|
for(blockIndex = file.blockIndex; file.block->next != BLOCK_EOF; blockIndex = file.blockIndex)
|
for(blockIndex = file.blockIndex; file.block->next != BLOCK_EOF; blockIndex = file.blockIndex)
|
Line 476... |
Line 602... |
if(file.blockLocal)
|
if(file.blockLocal)
|
free(file.blockLocal);
|
free(file.blockLocal);
|
}
|
}
|
if(dir.blockLocal)
|
if(dir.blockLocal)
|
free(dir.blockLocal);
|
free(dir.blockLocal);
|
|
OS_MutexPost(mutexFilesys);
|
}
|
}
|
|
|
|
|
int OS_fdir(OS_FILE *dir, char name[64])
|
int OS_fdir(OS_FILE *dir, char name[64])
|
{
|
{
|