* functions
*/
-u32 pffs_get_ptr(t_pffs *pffs,u8 sector) {
-
- u16 data[3];
- u32 iaddr;
- u32 daddr;
- u8 fnlen;
- u8 found;
+#define pffs_check_magic(data) (((data)&PFFS_INDEX_MAGIC_MASK)==PFFS_INDEX_MAGIC)
+#define pffs_fnlen(data) (((data)&PFFS_FNLEN_MASK)>>4)
+#define pffs_daddr_msb(data) (((data)&PFFS_LEN_MSB_MASK))
+#define pffs_sec_erase(pffs,sec) pffs->fe(pffs->base_addr|pffs->sec_addr[sec])
- iaddr=0;
- daddr=0;
- found=0;
+u32 pffs_find_index(t_pffs *pffs,u8 sector) {
- while(1) {
- pffs->fr(pffs->base_addr+pffs->sec_addr[sector]+iaddr,data,6);
- if(!((data[0]&0xff00)==PFFS_INDEX_MAGIC))
- break;
- found=1;
- fnlen=(data[0]&0x00f0)>>4;
- iaddr+=(6+fnlen+fnlen);
- daddr=((data[0]&0x000f)<<16)|data[1];
- }
+ u16 data;
- pffs->data_ptr=daddr;
+ pffs->fr(pffs->base_addr+pffs->sec_addr[sector],&data,2);
- if(found) {
- pffs->index_ptr[0]=pffs->sec_addr[sector];
- pffs->index_ptr[1]=pffs->sec_addr[sector]+iaddr;
- return 0;
+ if((data&0xf000)==PFFS_INDEX_MAGIC) {
+ pffs->index_sec=sector;
+ return PFFS_INDEX_FOUND;
}
- else
- return -1;
+
+ return PFFS_NO_INDEX_FOUND;
}
int pffs_sec_empty(t_pffs *pffs,u8 sec) {
addr=pffs->base_addr|pffs->sec_addr[sec];
while(addr<(pffs->base_addr|pffs->sec_addr[sec+1])) {
- data=*((u16 *)(addr));
+ pffs->fr(addr,&data,2);
if(data!=0xffff)
- return 0;
+ return PFFS_SEC_NOT_EMPTY;
addr+=2;
}
- return 1;
+ return PFFS_SEC_EMPTY;
}
-#define pffs_sec_erase(pffs,sec) pffs->fe(pffs->base_addr|pffs->sec_addr[sec])
+int pffs_find_data_tmp(t_pffs *pffs,u8 sector) {
+
+ u32 iaddr,daddr,dend,dstart;
+ u16 data[3];
+ u8 fnlen;
+
+ iaddr=pffs->base_addr|pffs->sec_addr[pffs->index_sec];
+ dstart=pffs->sec_addr[sector];
+ dend=pffs->sec_addr[sector+1];
+
+ while(iaddr<(pffs->base_addr|pffs->sec_addr[sector+1])) {
+ pffs->fr(iaddr,data,6);
+ if(pffs_check_magic(data[0]))
+ break;
+ daddr=pffs_daddr_msb(data[0])|data[1];
+ if((daddr+data[2]<dstart)|(daddr>=dend)) {
+ fnlen=pffs_fnlen(data[0]);
+ iaddr+=(6+fnlen+fnlen);
+ continue;
+ }
+ else
+ return PFFS_NO_DATA_TMP;
+ }
+
+ pffs->data_tmp_sec=sector;
+ if(pffs_sec_empty(pffs,sector)!=PFFS_SEC_EMPTY)
+ pffs->fe(pffs->base_addr|dstart);
+
+ return PFFS_DATA_TMP_FOUND;;
+}
int pffs_orientate(t_pffs *pffs) {
- u8 sec,sec0,sec1;
+ u8 sec,sec0,sec1,found;
- /* check index sectors */
sec0=pffs->sec_num_index[0];
sec1=pffs->sec_num_index[1];
- if(!(pffs_get_ptr(pffs,sec0)&pffs_get_ptr(pffs,sec1)))
- return 0;
+
+ found=0;
+
+ /* check index sectors */
+ if(pffs_find_index(pffs,sec0)==PFFS_INDEX_FOUND)
+ found=1;
+ else if(pffs_find_index(pffs,sec1)==PFFS_INDEX_FOUND)
+ found=1;
+
+ /* chose temp data sector */
+ if(found) {
+ sec0=pffs->sec_num_data[0];
+ sec1=pffs->sec_num_data[1];
+ for(sec=sec1;sec>=sec0;sec--)
+ if(pffs_find_data_tmp(pffs,sec)==PFFS_DATA_TMP_FOUND)
+ break;
+
+ return PFFS_INDEX_FOUND;
+ }
/* initial run => no data + no index assumed => check whether erased! */
// erase index sectors
pffs_sec_erase(pffs,sec0);
if(!pffs_sec_empty(pffs,sec1))
pffs_sec_erase(pffs,sec1);
+ pffs->index_sec=sec0;
// erase data sectors
sec0=pffs->sec_num_data[0];
sec1=pffs->sec_num_data[1];
+ pffs->data_tmp_sec=sec1;
for(sec=sec0;sec<=sec1;sec++)
if(!pffs_sec_empty(pffs,sec))
pffs_sec_erase(pffs,sec);
return 0;
}
-#define pffs_check_magic(data) (((data)&PFFS_INDEX_MAGIC_MASK)==PFFS_INDEX_MAGIC)
-#define pffs_fnlen(data) (((data)&PFFS_FNLEN_MASK)>>4)
-#define pffs_daddr_msb(data) (((data)&))
-
int pffs_find_file(t_pffs *pffs,char *file,u32 *iaddr,u32 *daddr,u16 *len) {
u8 fnl;
u16 data[PFFS_MAX_FILENAME_SIZE+PFFS_HEADER_SIZE];
- pffs->index_ptr[2]=pffs->base_addr|pffs->index_ptr[0];
+ *iaddr=pffs->base_addr|pffs->sec_addr[pffs->index_sec];
- while(pffs->index_ptr[2]<pffs->index_ptr[1])
- pffs->fr(iaddr,data,3);
+ while(*iaddr<pffs->sec_addr[pffs->index_sec]) {
+ pffs->fr(*iaddr,data,3);
if(!pffs_check_magic(data[0]))
break;
fnl=pffs_fnlen(data[0]);
- pffs->fr(iaddr+6,data+3,fnl+fnl);
+ pffs->fr(*iaddr+6,data+3,fnl+fnl);
- if(!strncmp(fd->file,(char *)(data+3),fnl+fnl)) {
- *daddr=((data[0]&0x000f)<<16)|data[1];
+ if(!strncmp(file,(char *)(data+3),fnl+fnl)) {
+ *daddr=pffs->base_addr|((data[0]&0x000f)<<16)|data[1];
*len=data[2];
- pffs->index_ptr[2]=*iaddr;
- return PFFS_FILE_EXISTS;
+ return PFFS_FILE_FOUND;
}
- pffs->fr(iaddr,data,3);
+
+ *iaddr+=(6+fnl+fnl);
}
return PFFS_FILE_NOT_FOUND;
}
-int pffs_open_read(t_pffs *pffs,t_pffs_fd *fd) {
+int pffs_open_read(t_pffs_fd *fd) {
- u32 iaddr;
- u32 daddr;
- u16 data[PFFS_MAX_FILENAME+PFFS_HEADER_SIZE];
+ int ret;
- iaddr=pffs->base_addr|pffs->index_ptr[0];
+ ret=pffs_find_file(fd->pffs,fd->file,
+ &(fd->iaddr),&(fd->daddr),&(fd->len));
+
+ if(ret==PFFS_FILE_FOUND) {
+ fd->dptr=fd->daddr;
+ fd->mode=PFFS_READ;
+ }
- return 0x23;
+ return ret;
}
+int pffs_open_write(t_pffs_fd *fd) {
+
+ int ret;
+
+ ret=pffs_find_file(fd->pffs,fd->file,
+ &(fd->iaddr),&(fd->daddr),&(fd->len));
+
+ switch(ret) {
+ case PFFS_FILE_NOT_FOUND:
+ fd->mode=PFFS_WRITE;
+ pffs_write_index_init();
+ fd->dptr=fd->daddr;
+ break;
+ case PFFS_FILE_FOUND:
+ default:
+ break;
+ }
+
+ return ret;
+}
+
int pffs_open(t_pffs *pffs,t_pffs_fd *fd,char *file,u8 mode) {
+ int ret;
+
/* the pffs struct */
fd->pffs=pffs;
/* filename */
fd->fn_size=strlen(file);
- if(fd->fn_size>30)
+ if(fd->fn_size>PFFS_MAX_FILENAME_SIZE+PFFS_MAX_FILENAME_SIZE)
return PFFS_FILENAME_TOO_LONG;
strncpy(fd->file,file,fd->fn_size);
if(fd->fn_size&1)
fd->file[fd->fn_size++]='\0';
- /* mode */
- fd->mode=mode;
+ /* clear fd mode */
+ fd->mode=0;
/* action */
switch(mode) {
case PFFS_READ:
- pffs_open_read(pffs,fd);
+ ret=pffs_open_read(fd);
break;
case PFFS_WRITE:
+ ret=pffs_open_write(fd);
break;
case PFFS_RDWR:
default:
return PFFS_MODE_UNSUPPORTED;
}
- return 0;
+ return ret;
+}
+
+int pffs_read(t_pffs_fd *fd,u8 *buf,int len) {
+
+ int missing;
+
+ /* check whether valid */
+ if(!(fd->mode&PFFS_READ))
+ return PFFS_EINVAL;
+
+ /* checl len */
+ if(len&1)
+ return PFFS_INVALID_LEN;
+
+ missing=fd->len-(fd->dptr-fd->daddr);
+ if(len>missing)
+ len=missing;
+
+ /* read */
+ fd->pffs->fr(fd->dptr,(u16 *)buf,len);
+ fd->dptr+=len;;
+
+ return len;
}
#define PFFS_MAX_FILENAME_SIZE 15 // in words
#define PFFS_HEADER_SIZE 3 // in words
-#define PFFS_REGISTERED (1<<0)
+/* general pffs system */
+#define PFFS_INDEX_FOUND 0x00
+#define PFFS_NO_INDEX_FOUND 0x01
-#define PFFS_INDEX_MAGIC 0x7000
+#define PFFS_DATA_TMP_FOUND 0x00
+#define PFFS_NO_DATA_TMP 0x01
+
+#define PFFS_SEC_NOT_EMPTY 0x00
+#define PFFS_SEC_EMPTY 0x01
+#define PFFS_REGISTERED (1<<0)
+
+/* pffs index format */
#define PFFS_INDEX_MAGIC_MASK 0xf000
-#define PFFS_RESERVED_MASK 0x0f00
+#define PFFS_STATE_MASK 0x0f00
#define PFFS_FNLEN_MASK 0x00f0
#define PFFS_LEN_MSB_MASK 0x000f
+#define PFFS_INDEX_MAGIC 0x7000
+#define PFFS_INDEX_REMOVED 0x0700
+
/* file modes */
#define PFFS_READ 0x01
#define PFFS_WRITE 0x02
#define PFFS_RDWR 0x03
-/* pffs write / read return codes */
-#define PFFS_FILE_EXISTS 0x01
+/* lseek offsets */
+#define PFFS_SEEK_SET 0x01
+#define PFFS_SEEK_CUR 0x02
+#define PFFS_SEEK_END 0x03
+
+/* pffs open / write / read return codes */
+#define PFFS_FILE_FOUND 0x01
#define PFFS_FILE_NOT_FOUND 0x02
#define PFFS_NO_SPACE_LEFT 0x04
#define PFFS_FILENAME_TOO_LONG 0x08
+#define PFFS_MODE_UNSUPPORTED 0x10
+
+#define PFFS_INVALID_LEN 0x01
+#define PFFS_EINVAL 0x02
/* type definitions */
/* flash specs */
u32 base_addr;
u32 *sec_addr;
+ u8 sec_num_data[2]; // first/last sector used for data
+ u8 sec_num_index[2]; // 2 sectors used as an index
+
/* flash write, read and sector erase function pointers */
int (*fw)(u32 addr,u16 *buf,int len);
int (*fr)(u32 addr,u16 *buf,int len);
int (*fe)(u32 addr);
+
/* pffs internal variables */
u8 state;
- u32 data_ptr; // pointer where new data goes
- u32 index_ptr[3]; // 0: start, 1: new, 2: current
- u8 sec_num_data[2]; // data start/end sectors
- u8 sec_num_index[2]; // 2 index sectors
+ u8 index_sec; // current index sector
+ u8 data_tmp_sec; // current temp data sector
} t_pffs;
typedef struct s_pffs_fd {
u32 daddr;
+ u32 dptr;
u32 iaddr;
+ u16 len;
char file[PFFS_MAX_FILENAME_SIZE+PFFS_MAX_FILENAME_SIZE];
u8 fn_size;
u8 mode;
} t_pffs_fd;
/* function prototypes */
-int pffs_open(t_pffs *pffs,char *file,u8 mode);
-int pffs_write(t_pffs *pffs,int fd,u8 *buf,int len);
-int pffs_read(t_pffs *pffs,int fd,u8 *buf,int len);
-int pffs_close(t_pffs *pffs,int fd);
-int pffs_unlink(t_pffs *pffs,char *file);
+int pffs_open(t_pffs *pffs,t_pffs_fd *fd,char *file,u8 mode);
+int pffs_write(t_pffs_fd *fd,u8 *buf,int len);
+int pffs_read(t_pffs_fd *fd,u8 *buf,int len);
+int pffs_lseek(t_pffs_fd *fd,u8 offset,int len);
+int pffs_close(t_pffs_fd *fd);
+int pffs_unlink(t_pffs_fd *fd,char *file);
#endif