From 5a0763175239659de98b905afdf5638ea59a26bb Mon Sep 17 00:00:00 2001 From: ksb Date: Sat, 11 Jul 2009 15:13:55 +0000 Subject: [PATCH] Common SD-card interface, implementing CFS using EFSL --- cpu/arm/common/SD-card/Makefile.sdcard | 10 ++ cpu/arm/common/SD-card/cfs-sdcard.c | 188 +++++++++++++++++++++++++ cpu/arm/common/SD-card/config.h | 125 ++++++++++++++++ cpu/arm/common/SD-card/efs-sdcard.h | 27 ++++ cpu/arm/common/SD-card/efsl_spi.h | 21 +++ cpu/arm/common/SD-card/sdcard.h | 22 +++ 6 files changed, 393 insertions(+) create mode 100644 cpu/arm/common/SD-card/Makefile.sdcard create mode 100644 cpu/arm/common/SD-card/cfs-sdcard.c create mode 100644 cpu/arm/common/SD-card/config.h create mode 100644 cpu/arm/common/SD-card/efs-sdcard.h create mode 100644 cpu/arm/common/SD-card/efsl_spi.h create mode 100644 cpu/arm/common/SD-card/sdcard.h diff --git a/cpu/arm/common/SD-card/Makefile.sdcard b/cpu/arm/common/SD-card/Makefile.sdcard new file mode 100644 index 000000000..0c1137127 --- /dev/null +++ b/cpu/arm/common/SD-card/Makefile.sdcard @@ -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 \ No newline at end of file diff --git a/cpu/arm/common/SD-card/cfs-sdcard.c b/cpu/arm/common/SD-card/cfs-sdcard.c new file mode 100644 index 000000000..9be29fd2e --- /dev/null +++ b/cpu/arm/common/SD-card/cfs-sdcard.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include + +#include + + + +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; +} diff --git a/cpu/arm/common/SD-card/config.h b/cpu/arm/common/SD-card/config.h new file mode 100644 index 000000000..0e09e88fe --- /dev/null +++ b/cpu/arm/common/SD-card/config.h @@ -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 diff --git a/cpu/arm/common/SD-card/efs-sdcard.h b/cpu/arm/common/SD-card/efs-sdcard.h new file mode 100644 index 000000000..ffc4968ba --- /dev/null +++ b/cpu/arm/common/SD-card/efs-sdcard.h @@ -0,0 +1,27 @@ +#ifndef __SDCARD_H__KJBBKS6O57__ +#define __SDCARD_H__KJBBKS6O57__ + +#include +#include +#include + +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__ */ diff --git a/cpu/arm/common/SD-card/efsl_spi.h b/cpu/arm/common/SD-card/efsl_spi.h new file mode 100644 index 000000000..6989c81aa --- /dev/null +++ b/cpu/arm/common/SD-card/efsl_spi.h @@ -0,0 +1,21 @@ +#ifndef __EFSL_SPI_H__6B6MX40N68__ +#define __EFSL_SPI_H__6B6MX40N68__ + +#include + +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__ */ diff --git a/cpu/arm/common/SD-card/sdcard.h b/cpu/arm/common/SD-card/sdcard.h new file mode 100644 index 000000000..fcca1461d --- /dev/null +++ b/cpu/arm/common/SD-card/sdcard.h @@ -0,0 +1,22 @@ +#ifndef __SDCARD_H__KJBBKS6O57__ +#define __SDCARD_H__KJBBKS6O57__ + +#include + +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__ */