Common SD-card interface, implementing CFS using EFSL
This commit is contained in:
parent
2c00620fc8
commit
5a07631752
6 changed files with 393 additions and 0 deletions
10
cpu/arm/common/SD-card/Makefile.sdcard
Normal file
10
cpu/arm/common/SD-card/Makefile.sdcard
Normal 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
|
188
cpu/arm/common/SD-card/cfs-sdcard.c
Normal file
188
cpu/arm/common/SD-card/cfs-sdcard.c
Normal 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;
|
||||||
|
}
|
125
cpu/arm/common/SD-card/config.h
Normal file
125
cpu/arm/common/SD-card/config.h
Normal 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
|
27
cpu/arm/common/SD-card/efs-sdcard.h
Normal file
27
cpu/arm/common/SD-card/efs-sdcard.h
Normal 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__ */
|
21
cpu/arm/common/SD-card/efsl_spi.h
Normal file
21
cpu/arm/common/SD-card/efsl_spi.h
Normal 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__ */
|
22
cpu/arm/common/SD-card/sdcard.h
Normal file
22
cpu/arm/common/SD-card/sdcard.h
Normal 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__ */
|
Loading…
Reference in a new issue