Common SD-card interface, implementing CFS using EFSL

This commit is contained in:
ksb 2009-07-11 15:13:55 +00:00
parent 2c00620fc8
commit 5a07631752
6 changed files with 393 additions and 0 deletions

View file

@ -0,0 +1,10 @@
ifdef SDCARD
EFSL_DIR=/home/ksb/packages/efsl/efsl-0.2.8
EFSL_SRC= efs.c fat.c sd.c fat.c partition.c ioman.c disc.c fs.c file.c plibc.c extract.c dir.c time.c ls.c ui.c
CONTIKI_CPU_DIRS += ../common/SD-card
CONTIKIDIRS += $(EFSL_DIR)/src $(EFSL_DIR)/src/interfaces
CONTIKI_TARGET_SOURCEFILES += $(EFSL_SRC) cfs-sdcard.c efs-sdcard-arch.c
CFLAGS+= -I $(EFSL_DIR)/inc -I $(CONTIKI_CPU_ARM_COMMON)/SD-card
endif

View file

@ -0,0 +1,188 @@
#include <efs-sdcard.h>
#include <sys/process.h>
#include <cfs/cfs.h>
#include <debug-uart.h>
#include <stdio.h>
process_event_t sdcard_inserted_event;
process_event_t sdcard_removed_event;
#define MAX_FDS 4
static File file_descriptors[MAX_FDS];
static int
find_free_fd()
{
int fd;
for (fd = 0; fd < MAX_FDS; fd++) {
if (!file_getAttr(&file_descriptors[fd], FILE_STATUS_OPEN)) {
return fd;
}
}
return -1;
}
static File *
get_file(int fd)
{
if (!sdcard_ready()) return 0;
if (fd >= MAX_FDS || fd < 0) return NULL;
if (!file_getAttr(&file_descriptors[fd], FILE_STATUS_OPEN)) return NULL;
return &file_descriptors[fd];
}
int
cfs_open (const char *name, int flags)
{
static int initialized = 0;
eint8 mode;
int fd;
if (!initialized) {
int fd;
/* Mark all file descriptors as free */
for (fd = 0; fd < MAX_FDS; fd++) {
file_setAttr(&file_descriptors[fd], FILE_STATUS_OPEN,0);
}
}
if (!sdcard_ready()) return -1;
fd = find_free_fd();
if (fd < 0) return -1;
if (flags == CFS_READ) {
mode = MODE_READ;
} else {
mode = MODE_APPEND;
}
if (file_fopen(&file_descriptors[fd], efs_sdcard_get_fs(),
(char*)name, mode) < 0) {
return -1;
}
return fd;
}
void
cfs_close(int fd)
{
File *file = get_file(fd);
if (!file) return;
file_fclose(file);
fs_flushFs(efs_sdcard_get_fs());
}
int
cfs_read (int fd, void *buf, unsigned int len)
{
File *file = get_file(fd);
if (!file) return 0;
return file_read(file, len, (euint8*)buf);
}
int
cfs_write (int fd, const void *buf, unsigned int len)
{
File *file = get_file(fd);
if (!file) return 0;
return file_write(file, len, (euint8*)buf);
}
cfs_offset_t
cfs_seek (int fd, cfs_offset_t offset, int whence)
{
File *file;
if (whence != CFS_SEEK_SET) return -1;
file = get_file(fd);
if (!file) return 0;
if (file_setpos(file, offset) != 0) return -1;
return file->FilePtr;
}
/* Cause a compile time error if expr is false */
#ifdef __GNUC__
#define COMPILE_TIME_CHECK(expr) \
(void) (__builtin_choose_expr ((expr), 0, ((void)0))+3)
#else
#define COMPILE_TIME_CHECK(expr)
#endif
#define MAX_DIR_LISTS 4
DirList dir_lists[MAX_DIR_LISTS];
static DirList *
find_free_dir_list()
{
unsigned int l;
for(l = 0; l < MAX_DIR_LISTS; l++) {
if (dir_lists[l].fs == NULL) {
return &dir_lists[l];
}
}
return NULL;
}
int
cfs_opendir (struct cfs_dir *dirp, const char *name)
{
DirList *dirs;
COMPILE_TIME_CHECK(sizeof(DirList*) <= sizeof(struct cfs_dir));
if (!sdcard_ready()) return -1;
dirs = find_free_dir_list();
if (!dirs) return -1;
if (ls_openDir(dirs, efs_sdcard_get_fs(), (eint8*)name) != 0) {
dirs->fs = NULL;
return -1;
}
*(DirList**)dirp = dirs;
return 0;
}
int
cfs_readdir (struct cfs_dir *dirp, struct cfs_dirent *dirent)
{
euint8 *start;
euint8 *end;
char *to = dirent->name;
DirList *dirs = *(DirList**)dirp;
if (!sdcard_ready()) return 1;
if (ls_getNext(dirs) != 0) return 1;
start = dirs->currentEntry.FileName;
end = start + 7;
while(end > start) {
if (*end > ' ') {
end++;
break;
}
end--;
}
while(start < end) {
*to++ = *start++;
}
start = dirs->currentEntry.FileName + 8;
end = start + 3;
if (*start > ' ') {
*to++ = '.';
*to++ = *start++;
while(start < end && *start > ' ') {
*to++ = *start++;
}
}
*to = '\0';
if (dirs->currentEntry.Attribute & ATTR_DIRECTORY) {
dirent->size = 0;
} else {
dirent->size = dirs->currentEntry.FileSize;
}
return 0;
}
void
cfs_closedir (struct cfs_dir *dirp)
{
(*(DirList**)dirp)->fs = NULL;
}

View file

@ -0,0 +1,125 @@
#ifndef __EFSL_CONFIG_H__
#define __EFSL_CONFIG_H__
/* Close enough */
#define HW_ENDPOINT_LPC2000_SD
/* Memory configuration
--------------------
* Here you must configure wheter your processor can access memory byte
* oriented. All x86 processors can do it, AVR's can do it to. Some DSP
* or other microcontrollers can't. If you have an 8 bit system you're safe.
* If you are really unsure, leave the setting commented out, it will be slower
* but it will work for sure.
*/
/* disabled for ARM (mt): #define BYTE_ALIGNMENT */
/* Cache configuration
-------------------
* Here you must configure how much memory of cache you can/want to use.
* The number you put at IOMAN_NUMBUFFER is multiplied by 512. So 1 means
* 512 bytes cache, 4 means 2048 bytes cache. More is better.
* The number after IOMAN_NUMITERATIONS should be untouched.
* The last field (IOMAN_DO_MEMALLOC) is to tell ioman to allocate it's
* own memory in it's structure, or not. If you choose to do it yourself
* you will have to pass a pointer to the memory as the last argument of
* ioman_init.
*/
/*#define IOMAN_NUMBUFFER 1*/
#define IOMAN_NUMBUFFER 6
#define IOMAN_NUMITERATIONS 3
#define IOMAN_DO_MEMALLOC
/* Cluster pre-allocation
----------------------
* When writing files, the function that performs the actual write has to
* calculate how many clusters it will need for that request. It then allocates
* that number of new clusters to the file. Since this involves some calculations
* and writing of the FAT, you might find it beneficial to limit the number of
* allocations, and allow fwrite to pre-allocate a number of clusters extra.
* This setting determines how many clusters will be extra allocated whenever
* this is required.
* Take in carefull consideration how large your clustersize is, putting 10 here
* with a clustersize of 32kb means you might waste 320 kb.
* The first option is for preallocating files, the other is used when enlarging
* a directory to accomodate more files
*/
/*#define CLUSTER_PREALLOC_FILE 0*/
#define CLUSTER_PREALLOC_FILE 2
#define CLUSTER_PREALLOC_DIRECTORY 0
/* Endianess configuration
-----------------------
* Here you can configure wheter your architecture is little or big endian. This
* is important since all FAT structures are stored in intel little endian order.
* So if you have a big endian system the library has to convert all figures to
* big endian in order to work.
*/
#define LITTLE_ENDIAN
/* Date and Time support
---------------------
* Here you can enable or disable date and time support. If you enable
* it you will have to create 6 functions, that are described in the
* EFSL manual. If the functions are not present when linking your
* program with the library you will get unresolved dependencies.
*/
/*#define DATE_TIME_SUPPORT*/
/* Error reporting support
-----------------------
* When you receive an error in userland, it usually only gives limited
* information (most likely, fail or success). If error detection and
* reporting is important for you, you can enable more detailed error
* reporting here. This is optional, the costs are 1 byte per object,
* and a small increase in code size.
* You can enable error recording for all object, or you can select the
* object manually.
* For full error reporting use FULL_ERROR_SUPPORT
* For only the base-core of the library use BASE_ERROR_SUPPORT
* For IO/Man use ERRSUP_IOMAN
* For Disc use ERRSUP_IOMAN
* For Part use ERRSUP_PARTITION
* For Fs use ERRSUP_FILESYSTEM
* For File use ERRSUP_FILE
*/
#define FULL_ERROR_SUPPORT
/*#define BASE_ERROR_SUPPORT*/
/* List options
------------
* In this section youcan configure what kind of data you will get from
* directory listing requests. Please refer to the documentation for
* more information
*/
#define LIST_MAXLENFILENAME 12
/* Debugging configuration
-----------------------
* Here you can configure the debugging behaviour. Debugging is different
* on every platform (see debug.h for more information).
* If your hardware has no means of output (printf) dont define any anything,
* and nothing will happen. For real world use debugging should be turned off.
*/
/* #define DEBUG */
#define lpc2000_debug_printf dbg_blocking_printf
#endif

View file

@ -0,0 +1,27 @@
#ifndef __SDCARD_H__KJBBKS6O57__
#define __SDCARD_H__KJBBKS6O57__
#include <efs.h>
#include <ls.h>
#include <sys/process.h>
PROCESS_NAME(sdcard_process);
void
efs_sdcard_init();
FileSystem *
efs_sdcard_get_fs();
/* True if a card is ready to read or write */
int
sdcard_ready();
extern process_event_t sdcard_inserted_event;
extern process_event_t sdcard_removed_event;
void
sdcard_event_process(struct process *p);
#endif /* __SDCARD_H__KJBBKS6O57__ */

View file

@ -0,0 +1,21 @@
#ifndef __EFSL_SPI_H__6B6MX40N68__
#define __EFSL_SPI_H__6B6MX40N68__
#include <types.h>
struct hwInterface{
eint32 sectorCount;
};
typedef struct hwInterface hwInterface;
esint8 if_initInterface(hwInterface* file,eint8* opts);
esint8 if_readBuf(hwInterface* file,euint32 address,euint8* buf);
esint8 if_writeBuf(hwInterface* file,euint32 address,euint8* buf);
esint8 if_setPos(hwInterface* file,euint32 address);
void if_spiInit(hwInterface *iface);
void if_spiSetSpeed(euint8 speed);
euint8 if_spiSend(hwInterface *iface, euint8 outgoing);
#endif /* __EFSL_SPI_H__6B6MX40N68__ */

View file

@ -0,0 +1,22 @@
#ifndef __SDCARD_H__KJBBKS6O57__
#define __SDCARD_H__KJBBKS6O57__
#include <sys/process.h>
PROCESS_NAME(sdcard_process);
void
sdcard_init();
/* True if a card is ready to read or write */
int
sdcard_ready();
extern process_event_t sdcard_inserted_event;
extern process_event_t sdcard_removed_event;
void
sdcard_event_process(struct process *p);
#endif /* __SDCARD_H__KJBBKS6O57__ */