Commit ecf8bd98 authored by Arnim Läuger's avatar Arnim Läuger Committed by Marcel Stör
Browse files

Add FatFs and SD card support (#1397)

* Add FatFs
* enable BUILD_FATFS for all-module build
* push vfs into rest of firmware
* align maximum filename length
* increase timeout for acmd41 during card initialization
* switch from DOS to Unix path semantics chdrive() is substituted by chdir()
* update to fatfs R.012a incl. patches 1-6
* add callback for rtc provisioning in file
* update docs
parent 99cd2177
This diff is collapsed.
This diff is collapsed.
/*------------------------------------------------------------------------*/
/* Sample code of OS dependent controls for FatFs */
/* (C)ChaN, 2014 */
/*------------------------------------------------------------------------*/
#include "../ff.h"
#if _FS_REENTRANT
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
int ret;
*sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
ret = (int)(*sobj != INVALID_HANDLE_VALUE);
// *sobj = SyncObjects[vol]; /* uITRON (give a static sync object) */
// ret = 1; /* The initial value of the semaphore must be 1. */
// *sobj = OSMutexCreate(0, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// *sobj = xSemaphoreCreateMutex(); /* FreeRTOS */
// ret = (int)(*sobj != NULL);
return ret;
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to any error */
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
int ret;
ret = CloseHandle(sobj); /* Win32 */
// ret = 1; /* uITRON (nothing to do) */
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// vSemaphoreDelete(sobj); /* FreeRTOS */
// ret = 1;
return ret;
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
_SYNC_t sobj /* Sync object to wait */
)
{
int ret;
ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
return ret;
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
_SYNC_t sobj /* Sync object to be signaled */
)
{
ReleaseMutex(sobj); /* Win32 */
// sig_sem(sobj); /* uITRON */
// OSMutexPost(sobj); /* uC/OS-II */
// xSemaphoreGive(sobj); /* FreeRTOS */
}
#endif
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free */
)
{
free(mblock); /* Discard the memory block with POSIX API */
}
#endif
#include "../ff.h"
#if _USE_LFN != 0
#if _CODE_PAGE == 932 /* Japanese Shift_JIS */
#include "cc932.c"
#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
#include "cc936.c"
#elif _CODE_PAGE == 949 /* Korean */
#include "cc949.c"
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
#include "cc950.c"
#else /* Single Byte Character-Set */
#include "ccsbcs.c"
#endif
#endif
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
#define SPI 0 #define SPI 0
#define HSPI 1 #define HSPI 1
#define SPI_ORDER_LSB 0
#define SPI_ORDER_MSB 1
//lcd drive function //lcd drive function
...@@ -18,7 +21,13 @@ void spi_lcd_mode_init(uint8 spi_no); ...@@ -18,7 +21,13 @@ void spi_lcd_mode_init(uint8 spi_no);
void spi_lcd_9bit_write(uint8 spi_no,uint8 high_bit,uint8 low_8bit); void spi_lcd_9bit_write(uint8 spi_no,uint8 high_bit,uint8 low_8bit);
//spi master init funtion //spi master init funtion
uint32_t spi_set_clkdiv(uint8 spi_no, uint32_t clock_div);
void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_div); void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_div);
void spi_mast_byte_order(uint8 spi_no, uint8 order);
// blocked buffer write
void spi_mast_blkset(uint8 spi_no, size_t bitlen, const uint8 *data);
// blocked buffer read
void spi_mast_blkget(uint8 spi_no, size_t bitlen, uint8 *data);
// fill MOSI buffer // fill MOSI buffer
void spi_mast_set_mosi(uint8 spi_no, uint16 offset, uint8 bitlen, uint32 data); void spi_mast_set_mosi(uint8 spi_no, uint16 offset, uint8 bitlen, uint32 data);
// retrieve data from MISO buffer // retrieve data from MISO buffer
......
#ifndef __FATFS_CONFIG_H__
#define __FATFS_CONFIG_H__
// don't redefine the PARTITION type
#ifndef _FATFS
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
#endif
// Table to map physical drive & partition to a logical volume.
// The first value is the physical drive and contains the GPIO pin for SS/CS of the SD card (default pin 8)
// The second value is the partition number.
#define NUM_LOGICAL_DRIVES 4
PARTITION VolToPart[NUM_LOGICAL_DRIVES] = {
{8, 1}, /* Logical drive "0:" ==> SS pin 8, 1st partition */
{8, 2}, /* Logical drive "1:" ==> SS pin 8, 2st partition */
{8, 3}, /* Logical drive "2:" ==> SS pin 8, 3st partition */
{8, 4} /* Logical drive "3:" ==> SS pin 8, 4st partition */
};
#endif /* __FATFS_CONFIG_H__ */
...@@ -68,9 +68,14 @@ extern void luaL_assertfail(const char *file, int line, const char *message); ...@@ -68,9 +68,14 @@ extern void luaL_assertfail(const char *file, int line, const char *message);
//#define MD2_ENABLE //#define MD2_ENABLE
#define SHA2_ENABLE #define SHA2_ENABLE
#define BUILD_SPIFFS 1 #define BUILD_SPIFFS
#define SPIFFS_CACHE 1 #define SPIFFS_CACHE 1
//#define BUILD_FATFS
// maximum length of a filename
#define FS_OBJ_NAME_LEN 31
// Uncomment this next line for fastest startup // Uncomment this next line for fastest startup
// It reduces the format time dramatically // It reduces the format time dramatically
// #define SPIFFS_MAX_FILESYSTEM_SIZE 32768 // #define SPIFFS_MAX_FILESYSTEM_SIZE 32768
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include C_HEADER_STDLIB #include C_HEADER_STDLIB
#include C_HEADER_STRING #include C_HEADER_STRING
#ifndef LUA_CROSS_COMPILER #ifndef LUA_CROSS_COMPILER
#include "flash_fs.h" #include "vfs.h"
#else #else
#endif #endif
...@@ -671,8 +671,8 @@ static const char *getFSF (lua_State *L, void *ud, size_t *size) { ...@@ -671,8 +671,8 @@ static const char *getFSF (lua_State *L, void *ud, size_t *size) {
return "\n"; return "\n";
} }
if (fs_eof(lf->f)) return NULL; if (vfs_eof(lf->f)) return NULL;
*size = fs_read(lf->f, lf->buff, sizeof(lf->buff)); *size = vfs_read(lf->f, lf->buff, sizeof(lf->buff));
return (*size > 0) ? lf->buff : NULL; return (*size > 0) ? lf->buff : NULL;
} }
...@@ -697,29 +697,29 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) { ...@@ -697,29 +697,29 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
} }
else { else {
lua_pushfstring(L, "@%s", filename); lua_pushfstring(L, "@%s", filename);
lf.f = fs_open(filename, FS_RDONLY); lf.f = vfs_open(filename, "r");
if (lf.f < FS_OPEN_OK) return errfsfile(L, "open", fnameindex); if (!lf.f) return errfsfile(L, "open", fnameindex);
} }
// if(fs_size(lf.f)>LUAL_BUFFERSIZE) // if(fs_size(lf.f)>LUAL_BUFFERSIZE)
// return luaL_error(L, "file is too big"); // return luaL_error(L, "file is too big");
c = fs_getc(lf.f); c = vfs_getc(lf.f);
if (c == '#') { /* Unix exec. file? */ if (c == '#') { /* Unix exec. file? */
lf.extraline = 1; lf.extraline = 1;
while ((c = fs_getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ while ((c = vfs_getc(lf.f)) != VFS_EOF && c != '\n') ; /* skip first line */
if (c == '\n') c = fs_getc(lf.f); if (c == '\n') c = vfs_getc(lf.f);
} }
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
fs_close(lf.f); vfs_close(lf.f);
lf.f = fs_open(filename, FS_RDONLY); /* reopen in binary mode */ lf.f = vfs_open(filename, "r"); /* reopen in binary mode */
if (lf.f < FS_OPEN_OK) return errfsfile(L, "reopen", fnameindex); if (!lf.f) return errfsfile(L, "reopen", fnameindex);
/* skip eventual `#!...' */ /* skip eventual `#!...' */
while ((c = fs_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; while ((c = vfs_getc(lf.f)) != VFS_EOF && c != LUA_SIGNATURE[0]) ;
lf.extraline = 0; lf.extraline = 0;
} }
fs_ungetc(c, lf.f); vfs_ungetc(c, lf.f);
status = lua_load(L, getFSF, &lf, lua_tostring(L, -1)); status = lua_load(L, getFSF, &lf, lua_tostring(L, -1));
if (filename) fs_close(lf.f); /* close file (even in case of errors) */ if (filename) vfs_close(lf.f); /* close file (even in case of errors) */
lua_remove(L, fnameindex); lua_remove(L, fnameindex);
return status; return status;
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "c_stdio.h" #include "c_stdio.h"
#include "c_stdlib.h" #include "c_stdlib.h"
#include "c_string.h" #include "c_string.h"
#include "flash_fs.h" #include "vfs.h"
#define liolib_c #define liolib_c
#define LUA_LIB #define LUA_LIB
...@@ -39,7 +39,7 @@ static const int liolib_keys[] = {(int)&luaL_callmeta, (int)&luaL_typerror, (int ...@@ -39,7 +39,7 @@ static const int liolib_keys[] = {(int)&luaL_callmeta, (int)&luaL_typerror, (int
static const char *const fnames[] = {"input", "output"}; static const char *const fnames[] = {"input", "output"};
static int pushresult (lua_State *L, int i, const char *filename) { static int pushresult (lua_State *L, int i, const char *filename) {
int en = fs_error(0); /* calls to Lua API may change this value */ int en = vfs_ferrno(0); /* calls to Lua API may change this value */
if (i) { if (i) {
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
...@@ -57,7 +57,7 @@ static int pushresult (lua_State *L, int i, const char *filename) { ...@@ -57,7 +57,7 @@ static int pushresult (lua_State *L, int i, const char *filename) {
static void fileerror (lua_State *L, int arg, const char *filename) { static void fileerror (lua_State *L, int arg, const char *filename) {
lua_pushfstring(L, "%s: err(%d)", filename, fs_error(0)); lua_pushfstring(L, "%s: err(%d)", filename, vfs_ferrno(0));
luaL_argerror(L, arg, lua_tostring(L, -1)); luaL_argerror(L, arg, lua_tostring(L, -1));
} }
...@@ -130,7 +130,7 @@ static int io_pclose (lua_State *L) { ...@@ -130,7 +130,7 @@ static int io_pclose (lua_State *L) {
*/ */
static int io_fclose (lua_State *L) { static int io_fclose (lua_State *L) {
int *p = tofilep(L); int *p = tofilep(L);
int ok = (fs_close(*p) == 0); int ok = (vfs_close(*p) == 0);
*p = FS_OPEN_OK - 1; *p = FS_OPEN_OK - 1;
return pushresult(L, ok, NULL); return pushresult(L, ok, NULL);
} }
...@@ -149,7 +149,7 @@ static int aux_close (lua_State *L) { ...@@ -149,7 +149,7 @@ static int aux_close (lua_State *L) {
lua_pushliteral(L, "cannot close standard file"); lua_pushliteral(L, "cannot close standard file");
return 2; return 2;
} }
int ok = (fs_close(*p) == 0); int ok = (vfs_close(*p) == 0);
*p = FS_OPEN_OK - 1; *p = FS_OPEN_OK - 1;
return pushresult(L, ok, NULL); return pushresult(L, ok, NULL);
#endif #endif
...@@ -187,7 +187,7 @@ static int io_open (lua_State *L) { ...@@ -187,7 +187,7 @@ static int io_open (lua_State *L) {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r"); const char *mode = luaL_optstring(L, 2, "r");
int *pf = newfile(L); int *pf = newfile(L);
*pf = fs_open(filename, fs_mode2flag(mode)); *pf = vfs_open(filename, mode);
return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1; return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1;
} }
...@@ -201,7 +201,7 @@ static int io_popen (lua_State *L) { ...@@ -201,7 +201,7 @@ static int io_popen (lua_State *L) {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r"); const char *mode = luaL_optstring(L, 2, "r");
int *pf = newfile(L); int *pf = newfile(L);
*pf = lua_popen(L, filename, fs_mode2flag(mode)); *pf = lua_popen(L, filename, fs_mode2flags(mode));
return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1; return (*pf == FS_OPEN_OK - 1) ? pushresult(L, 0, filename) : 1;
} }
...@@ -230,7 +230,7 @@ static int g_iofile (lua_State *L, int f, const char *mode) { ...@@ -230,7 +230,7 @@ static int g_iofile (lua_State *L, int f, const char *mode) {
const char *filename = lua_tostring(L, 1); const char *filename = lua_tostring(L, 1);
if (filename) { if (filename) {
int *pf = newfile(L); int *pf = newfile(L);
*pf = fs_open(filename, fs_mode2flag(mode)); *pf = vfs_open(filename, mode);
if (*pf == FS_OPEN_OK - 1) if (*pf == FS_OPEN_OK - 1)
fileerror(L, 1, filename); fileerror(L, 1, filename);
} }
...@@ -282,7 +282,7 @@ static int io_lines (lua_State *L) { ...@@ -282,7 +282,7 @@ static int io_lines (lua_State *L) {
else { else {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
int *pf = newfile(L); int *pf = newfile(L);
*pf = fs_open(filename, FS_RDONLY); *pf = vfs_open(filename, "r");
if (*pf == FS_OPEN_OK - 1) if (*pf == FS_OPEN_OK - 1)
fileerror(L, 1, filename); fileerror(L, 1, filename);
aux_lines(L, lua_gettop(L), 1); aux_lines(L, lua_gettop(L), 1);
...@@ -312,8 +312,8 @@ static int read_number (lua_State *L, int f) { ...@@ -312,8 +312,8 @@ static int read_number (lua_State *L, int f) {
#endif #endif
static int test_eof (lua_State *L, int f) { static int test_eof (lua_State *L, int f) {
int c = fs_getc(f); int c = vfs_getc(f);
fs_ungetc(c, f); vfs_ungetc(c, f);
lua_pushlstring(L, NULL, 0); lua_pushlstring(L, NULL, 0);
return (c != EOF); return (c != EOF);
} }
...@@ -347,7 +347,7 @@ static int read_line (lua_State *L, int f) { ...@@ -347,7 +347,7 @@ static int read_line (lua_State *L, int f) {
signed char c = EOF; signed char c = EOF;
int i = 0; int i = 0;
do{ do{
c = (signed char)fs_getc(f); c = (signed char)vfs_getc(f);
if(c==EOF){ if(c==EOF){
break; break;
} }
...@@ -377,7 +377,7 @@ static int read_chars (lua_State *L, int f, size_t n) { ...@@ -377,7 +377,7 @@ static int read_chars (lua_State *L, int f, size_t n) {
do { do {
char *p = luaL_prepbuffer(&b); char *p = luaL_prepbuffer(&b);
if (rlen > n) rlen = n; /* cannot read more than asked */ if (rlen > n) rlen = n; /* cannot read more than asked */
nr = fs_read(f, p, rlen); nr = vfs_read(f, p, rlen);
luaL_addsize(&b, nr); luaL_addsize(&b, nr);
n -= nr; /* still have to read `n' chars */ n -= nr; /* still have to read `n' chars */
} while (n > 0 && nr == rlen); /* until end of count or eof */ } while (n > 0 && nr == rlen); /* until end of count or eof */
...@@ -390,7 +390,7 @@ static int g_read (lua_State *L, int f, int first) { ...@@ -390,7 +390,7 @@ static int g_read (lua_State *L, int f, int first) {
int nargs = lua_gettop(L) - 1; int nargs = lua_gettop(L) - 1;
int success; int success;
int n; int n;
fs_clearerr(f); //vfs_clearerr(f);
if (nargs == 0) { /* no arguments? */ if (nargs == 0) { /* no arguments? */
success = read_line(L, f); success = read_line(L, f);
n = first+1; /* to return 1 result */ n = first+1; /* to return 1 result */
...@@ -425,7 +425,7 @@ static int g_read (lua_State *L, int f, int first) { ...@@ -425,7 +425,7 @@ static int g_read (lua_State *L, int f, int first) {
} }
} }
} }
if (fs_error(f)) if (vfs_ferrno(f))
return pushresult(L, 0, NULL); return pushresult(L, 0, NULL);
if (!success) { if (!success) {
lua_pop(L, 1); /* remove last result */ lua_pop(L, 1); /* remove last result */
...@@ -453,8 +453,8 @@ static int io_readline (lua_State *L) { ...@@ -453,8 +453,8 @@ static int io_readline (lua_State *L) {
return 0; return 0;
} }
sucess = read_line(L, *pf); sucess = read_line(L, *pf);
if (fs_error(*pf)) if (vfs_ferrno(*pf))
return luaL_error(L, "err(%d)", fs_error(*pf)); return luaL_error(L, "err(%d)", vfs_ferrno(*pf));
if (sucess) return 1; if (sucess) return 1;
else { /* EOF */ else { /* EOF */
if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
...@@ -484,7 +484,7 @@ static int g_write (lua_State *L, int f, int arg) { ...@@ -484,7 +484,7 @@ static int g_write (lua_State *L, int f, int arg) {
{ {
size_t l; size_t l;
const char *s = luaL_checklstring(L, arg, &l); const char *s = luaL_checklstring(L, arg, &l);
status = status && (fs_write(f, s, l) == l); status = status && (vfs_write(f, s, l) == l);
} }
} }
return pushresult(L, status, NULL); return pushresult(L, status, NULL);
...@@ -502,16 +502,16 @@ static int f_write (lua_State *L) { ...@@ -502,16 +502,16 @@ static int f_write (lua_State *L) {
static int f_seek (lua_State *L) { static int f_seek (lua_State *L) {
static const int mode[] = {FS_SEEK_SET, FS_SEEK_CUR, FS_SEEK_END}; static const int mode[] = {VFS_SEEK_SET, VFS_SEEK_CUR, VFS_SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL}; static const char *const modenames[] = {"set", "cur", "end", NULL};
int f = tofile(L); int f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames); int op = luaL_checkoption(L, 2, "cur", modenames);
long offset = luaL_optlong(L, 3, 0); long offset = luaL_optlong(L, 3, 0);
op = fs_seek(f, offset, mode[op]); op = vfs_lseek(f, offset, mode[op]);
if (op) if (op)
return pushresult(L, 0, NULL); /* error */ return pushresult(L, 0, NULL); /* error */
else { else {
lua_pushinteger(L, fs_tell(f)); lua_pushinteger(L, vfs_tell(f));
return 1; return 1;
} }
} }
...@@ -530,12 +530,12 @@ static int f_setvbuf (lua_State *L) { ...@@ -530,12 +530,12 @@ static int f_setvbuf (lua_State *L) {
static int io_flush (lua_State *L) { static int io_flush (lua_State *L) {
return pushresult(L, fs_flush(getiofile(L, IO_OUTPUT)) == 0, NULL); return pushresult(L, vfs_flush(getiofile(L, IO_OUTPUT)) == 0, NULL);
} }
static int f_flush (lua_State *L) { static int f_flush (lua_State *L) {
return pushresult(L, fs_flush(tofile(L)) == 0, NULL); return pushresult(L, vfs_flush(tofile(L)) == 0, NULL);
} }
#undef MIN_OPT_LEVEL #undef MIN_OPT_LEVEL
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include C_HEADER_FCNTL #include C_HEADER_FCNTL
#ifndef LUA_CROSS_COMPILER #ifndef LUA_CROSS_COMPILER
#include "flash_fs.h" #include "vfs.h"
#endif #endif
#include "lauxlib.h" #include "lauxlib.h"
...@@ -340,9 +340,9 @@ static int readable (const char *filename) { ...@@ -340,9 +340,9 @@ static int readable (const char *filename) {
} }
#else #else
static int readable (const char *filename) { static int readable (const char *filename) {
int f = fs_open(filename, FS_RDONLY); /* try to open file */ int f = vfs_open(filename, "r"); /* try to open file */
if (f < FS_OPEN_OK) return 0; /* open failed */ if (!f) return 0; /* open failed */
fs_close(f); vfs_close(f);
return 1; return 1;
} }
#endif #endif
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "c_stdio.h" #include "c_stdio.h"
#include "c_stdlib.h" #include "c_stdlib.h"
#include "c_string.h" #include "c_string.h"
#include "flash_fs.h" #include "user_interface.h"
#include "user_version.h" #include "user_version.h"
#include "driver/readline.h" #include "driver/readline.h"
#include "driver/uart.h" #include "driver/uart.h"
......
...@@ -52,6 +52,7 @@ INCLUDES += -I ../spiffs ...@@ -52,6 +52,7 @@ INCLUDES += -I ../spiffs
INCLUDES += -I ../smart INCLUDES += -I ../smart
INCLUDES += -I ../cjson INCLUDES += -I ../cjson
INCLUDES += -I ../dhtlib INCLUDES += -I ../dhtlib
INCLUDES += -I ../fatfs
INCLUDES += -I ../http INCLUDES += -I ../http
INCLUDES += -I ../websocket INCLUDES += -I ../websocket
PDIR := ../$(PDIR) PDIR := ../$(PDIR)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include "platform.h" #include "platform.h"
#include "c_types.h" #include "c_types.h"
#include "c_stdlib.h" #include "c_stdlib.h"
#include "flash_fs.h" #include "vfs.h"
#include "../crypto/digests.h" #include "../crypto/digests.h"
#include "../crypto/mech.h" #include "../crypto/mech.h"
...@@ -243,6 +243,11 @@ static int crypto_hash_gcdelete (lua_State *L) ...@@ -243,6 +243,11 @@ static int crypto_hash_gcdelete (lua_State *L)
} }
static sint32_t vfs_read_wrap (int fd, void *ptr, size_t len)
{
return vfs_read (fd, ptr, len);
}
/* rawdigest = crypto.hash("MD5", filename) /* rawdigest = crypto.hash("MD5", filename)
* strdigest = crypto.toHex(rawdigest) * strdigest = crypto.toHex(rawdigest)
*/ */
...@@ -254,17 +259,17 @@ static int crypto_flhash (lua_State *L) ...@@ -254,17 +259,17 @@ static int crypto_flhash (lua_State *L)
const char *filename = luaL_checkstring (L, 2); const char *filename = luaL_checkstring (L, 2);
// Open the file // Open the file
int file_fd = fs_open (filename, FS_RDONLY); int file_fd = vfs_open (filename, "r");
if(file_fd < FS_OPEN_OK) { if(!file_fd) {
return bad_file(L); return bad_file(L);
} }
// Compute hash // Compute hash
uint8_t digest[mi->digest_size]; uint8_t digest[mi->digest_size];
int returncode = crypto_fhash (mi, &fs_read, file_fd, digest); int returncode = crypto_fhash (mi, &vfs_read_wrap, file_fd, digest);
// Finish up // Finish up
fs_close(file_fd); vfs_close(file_fd);
if (returncode == ENOMEM) if (returncode == ENOMEM)
return bad_mem (L); return bad_mem (L);
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#include "espconn.h" #include "espconn.h"
#include "lwip/tcp.h" #include "lwip/tcp.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "flash_fs.h" #include "vfs.h"
#include "task/task.h" #include "task/task.h"
#define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y))
...@@ -485,20 +485,20 @@ static int enduser_setup_http_load_payload(void) ...@@ -485,20 +485,20 @@ static int enduser_setup_http_load_payload(void)
{ {
ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload"); ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload");
int err = (FS_OPEN_OK -1); int err = VFS_RES_ERR;
int err2 = (FS_OPEN_OK -1); int err2 = VFS_RES_ERR;
int file_len = 0; int file_len = 0;
int f = fs_open(http_html_filename, fs_mode2flag("r")); int f = vfs_open(http_html_filename, "r");
if (f >= FS_OPEN_OK) { if (f) {
err = fs_seek(f, 0, FS_SEEK_END); err = vfs_lseek(f, 0, VFS_SEEK_END);
file_len = (int) fs_tell(f); file_len = (int) vfs_tell(f);
err2 = fs_seek(f, 0, FS_SEEK_SET); err2 = vfs_lseek(f, 0, VFS_SEEK_SET);
} }
const char cl_hdr[] = "Content-length:%5d\r\n\r\n"; const char cl_hdr[] = "Content-length:%5d\r\n\r\n";
const size_t cl_len = LITLEN(cl_hdr) + 3; /* room to expand %4d */ const size_t cl_len = LITLEN(cl_hdr) + 3; /* room to expand %4d */
if (f < FS_OPEN_OK || err < FS_OPEN_OK || err2 < FS_OPEN_OK) if (!f || err != VFS_RES_OK || err2 != VFS_RES_OK)
{ {
ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload unable to load file enduser_setup.html, loading backup HTML."); ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload unable to load file enduser_setup.html, loading backup HTML.");
...@@ -531,8 +531,8 @@ static int enduser_setup_http_load_payload(void) ...@@ -531,8 +531,8 @@ static int enduser_setup_http_load_payload(void)
c_memcpy(&(state->http_payload_data[offset]), &(http_header_200), LITLEN(http_header_200)); c_memcpy(&(state->http_payload_data[offset]), &(http_header_200), LITLEN(http_header_200));
offset += LITLEN(http_header_200); offset += LITLEN(http_header_200);
offset += c_sprintf(state->http_payload_data + offset, cl_hdr, file_len); offset += c_sprintf(state->http_payload_data + offset, cl_hdr, file_len);
fs_read(f, &(state->http_payload_data[offset]), file_len); vfs_read(f, &(state->http_payload_data[offset]), file_len);
fs_close(f); vfs_close(f);
return 0; return 0;
} }
......
...@@ -5,42 +5,95 @@ ...@@ -5,42 +5,95 @@
#include "platform.h" #include "platform.h"
#include "c_types.h" #include "c_types.h"
#include "flash_fs.h" #include "vfs.h"
#include "c_string.h" #include "c_string.h"
static volatile int file_fd = FS_OPEN_OK - 1; static int file_fd = 0;
static int rtc_cb_ref = LUA_NOREF;
// Lua: open(filename, mode)
static int file_open( lua_State* L ) static void table2tm( lua_State *L, vfs_time *tm )
{ {
size_t len; int idx = lua_gettop( L );
if((FS_OPEN_OK - 1)!=file_fd){
fs_close(file_fd); // extract items from table
file_fd = FS_OPEN_OK - 1; lua_getfield( L, idx, "year" );
} lua_getfield( L, idx, "mon" );
lua_getfield( L, idx, "day" );
lua_getfield( L, idx, "hour" );
lua_getfield( L, idx, "min" );
lua_getfield( L, idx, "sec" );
tm->year = luaL_optint( L, ++idx, 2016 );
tm->mon = luaL_optint( L, ++idx, 6 );
tm->day = luaL_optint( L, ++idx, 21 );
tm->hour = luaL_optint( L, ++idx, 0 );
tm->min = luaL_optint( L, ++idx, 0 );
tm->sec = luaL_optint( L, ++idx, 0 );
// remove items from stack
lua_pop( L, 6 );
}
const char *fname = luaL_checklstring( L, 1, &len ); static sint32_t file_rtc_cb( vfs_time *tm )
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(fname) == len, 1, "filename invalid"); {
sint32_t res = VFS_RES_ERR;
const char *mode = luaL_optstring(L, 2, "r"); if (rtc_cb_ref != LUA_NOREF) {
lua_State *L = lua_getstate();
file_fd = fs_open(fname, fs_mode2flag(mode)); lua_rawgeti( L, LUA_REGISTRYINDEX, rtc_cb_ref );
lua_call( L, 0, 1 );
if(file_fd < FS_OPEN_OK){ if (lua_type( L, lua_gettop( L ) ) == LUA_TTABLE) {
file_fd = FS_OPEN_OK - 1; table2tm( L, tm );
lua_pushnil(L); res = VFS_RES_OK;
} else { }
lua_pushboolean(L, 1);
// pop item returned by callback
lua_pop( L, 1 );
} }
return 1;
return res;
}
// Lua: on()
static int file_on(lua_State *L)
{
enum events{
ON_RTC = 0
};
const char *const eventnames[] = {"rtc", NULL};
int event = luaL_checkoption(L, 1, "rtc", eventnames);
switch (event) {
case ON_RTC:
luaL_unref(L, LUA_REGISTRYINDEX, rtc_cb_ref);
if ((lua_type(L, 2) == LUA_TFUNCTION) ||
(lua_type(L, 2) == LUA_TLIGHTFUNCTION)) {
lua_pushvalue(L, 2); // copy argument (func) to the top of stack
rtc_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
vfs_register_rtc_cb(file_rtc_cb);
} else {
rtc_cb_ref = LUA_NOREF;
vfs_register_rtc_cb(NULL);
}
break;
default:
break;
}
return 0;
} }
// Lua: close() // Lua: close()
static int file_close( lua_State* L ) static int file_close( lua_State* L )
{ {
if((FS_OPEN_OK - 1)!=file_fd){ if(file_fd){
fs_close(file_fd); vfs_close(file_fd);
file_fd = FS_OPEN_OK - 1; file_fd = 0;
} }
return 0; return 0;
} }
...@@ -50,7 +103,7 @@ static int file_format( lua_State* L ) ...@@ -50,7 +103,7 @@ static int file_format( lua_State* L )
{ {
size_t len; size_t len;
file_close(L); file_close(L);
if( !fs_format() ) if( !vfs_format() )
{ {
NODE_ERR( "\n*** ERROR ***: unable to format. FS might be compromised.\n" ); NODE_ERR( "\n*** ERROR ***: unable to format. FS might be compromised.\n" );
NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" ); NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" );
...@@ -59,44 +112,77 @@ static int file_format( lua_State* L ) ...@@ -59,44 +112,77 @@ static int file_format( lua_State* L )
else{ else{
NODE_ERR( "format done.\n" ); NODE_ERR( "format done.\n" );
} }
return 0; return 0;
} }
#if defined(BUILD_SPIFFS) static int file_fscfg (lua_State *L)
{
uint32_t phys_addr, phys_size;
vfs_fscfg("/FLASH", &phys_addr, &phys_size);
extern spiffs fs; lua_pushinteger (L, phys_addr);
lua_pushinteger (L, phys_size);
return 2;
}
// Lua: open(filename, mode)
static int file_open( lua_State* L )
{
size_t len;
if(file_fd){
vfs_close(file_fd);
file_fd = 0;
}
const char *fname = luaL_checklstring( L, 1, &len );
const char *basename = vfs_basename( fname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");
const char *mode = luaL_optstring(L, 2, "r");
file_fd = vfs_open(fname, mode);
if(!file_fd){
lua_pushnil(L);
} else {
lua_pushboolean(L, 1);
}
return 1;
}
// Lua: list() // Lua: list()
static int file_list( lua_State* L ) static int file_list( lua_State* L )
{ {
spiffs_DIR d; vfs_dir *dir;
struct spiffs_dirent e; vfs_item *item;
struct spiffs_dirent *pe = &e;
if (dir = vfs_opendir("")) {
lua_newtable( L ); lua_newtable( L );
SPIFFS_opendir(&fs, "/", &d); while (item = vfs_readdir(dir)) {
while ((pe = SPIFFS_readdir(&d, pe))) { lua_pushinteger(L, vfs_item_size(item));
// NODE_ERR(" %s size:%i\n", pe->name, pe->size); lua_setfield(L, -2, vfs_item_name(item));
lua_pushinteger(L, pe->size); vfs_closeitem(item);
lua_setfield( L, -2, pe->name ); }
vfs_closedir(dir);
return 1;
} }
SPIFFS_closedir(&d); return 0;
return 1;
} }
static int file_seek (lua_State *L) static int file_seek (lua_State *L)
{ {
static const int mode[] = {FS_SEEK_SET, FS_SEEK_CUR, FS_SEEK_END}; static const int mode[] = {VFS_SEEK_SET, VFS_SEEK_CUR, VFS_SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL}; static const char *const modenames[] = {"set", "cur", "end", NULL};
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
int op = luaL_checkoption(L, 1, "cur", modenames); int op = luaL_checkoption(L, 1, "cur", modenames);
long offset = luaL_optlong(L, 2, 0); long offset = luaL_optlong(L, 2, 0);
op = fs_seek(file_fd, offset, mode[op]); op = vfs_lseek(file_fd, offset, mode[op]);
if (op < 0) if (op < 0)
lua_pushnil(L); /* error */ lua_pushnil(L); /* error */
else else
lua_pushinteger(L, fs_tell(file_fd)); lua_pushinteger(L, vfs_tell(file_fd));
return 1; return 1;
} }
...@@ -105,12 +191,14 @@ static int file_exists( lua_State* L ) ...@@ -105,12 +191,14 @@ static int file_exists( lua_State* L )
{ {
size_t len; size_t len;
const char *fname = luaL_checklstring( L, 1, &len ); const char *fname = luaL_checklstring( L, 1, &len );
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(fname) == len, 1, "filename invalid"); const char *basename = vfs_basename( fname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");
spiffs_stat stat; vfs_item *stat = vfs_stat((char *)fname);
int rc = SPIFFS_stat(&fs, (char *)fname, &stat);
lua_pushboolean(L, (rc == SPIFFS_OK ? 1 : 0)); lua_pushboolean(L, stat ? 1 : 0);
if (stat) vfs_closeitem(stat);
return 1; return 1;
} }
...@@ -120,49 +208,43 @@ static int file_remove( lua_State* L ) ...@@ -120,49 +208,43 @@ static int file_remove( lua_State* L )
{ {
size_t len; size_t len;
const char *fname = luaL_checklstring( L, 1, &len ); const char *fname = luaL_checklstring( L, 1, &len );
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(fname) == len, 1, "filename invalid"); const char *basename = vfs_basename( fname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");
file_close(L); file_close(L);
SPIFFS_remove(&fs, (char *)fname); vfs_remove((char *)fname);
return 0; return 0;
} }
// Lua: flush() // Lua: flush()
static int file_flush( lua_State* L ) static int file_flush( lua_State* L )
{ {
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
if(fs_flush(file_fd) == 0) if(vfs_flush(file_fd) == 0)
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
else else
lua_pushnil(L); lua_pushnil(L);
return 1; return 1;
} }
#if 0
// Lua: check()
static int file_check( lua_State* L )
{
file_close(L);
lua_pushinteger(L, fs_check());
return 1;
}
#endif
// Lua: rename("oldname", "newname") // Lua: rename("oldname", "newname")
static int file_rename( lua_State* L ) static int file_rename( lua_State* L )
{ {
size_t len; size_t len;
if((FS_OPEN_OK - 1)!=file_fd){ if(file_fd){
fs_close(file_fd); vfs_close(file_fd);
file_fd = FS_OPEN_OK - 1; file_fd = 0;
} }
const char *oldname = luaL_checklstring( L, 1, &len ); const char *oldname = luaL_checklstring( L, 1, &len );
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(oldname) == len, 1, "filename invalid"); const char *basename = vfs_basename( oldname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(oldname) == len, 1, "filename invalid");
const char *newname = luaL_checklstring( L, 2, &len ); const char *newname = luaL_checklstring( L, 2, &len );
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(newname) == len, 2, "filename invalid"); basename = vfs_basename( newname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(newname) == len, 2, "filename invalid");
if(SPIFFS_OK==myspiffs_rename( oldname, newname )){ if(0 <= vfs_rename( oldname, newname )){
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
} else { } else {
lua_pushboolean(L, 0); lua_pushboolean(L, 0);
...@@ -170,26 +252,6 @@ static int file_rename( lua_State* L ) ...@@ -170,26 +252,6 @@ static int file_rename( lua_State* L )
return 1; return 1;
} }
// Lua: fsinfo()
static int file_fsinfo( lua_State* L )
{
u32_t total, used;
if (SPIFFS_info(&fs, &total, &used)) {
return luaL_error(L, "file system failed");
}
NODE_DBG("total: %d, used:%d\n", total, used);
if(total>0x7FFFFFFF || used>0x7FFFFFFF || used > total)
{
return luaL_error(L, "file system error");
}
lua_pushinteger(L, total-used);
lua_pushinteger(L, used);
lua_pushinteger(L, total);
return 3;
}
#endif
// g_read() // g_read()
static int file_g_read( lua_State* L, int n, int16_t end_char ) static int file_g_read( lua_State* L, int n, int16_t end_char )
{ {
...@@ -199,14 +261,14 @@ static int file_g_read( lua_State* L, int n, int16_t end_char ) ...@@ -199,14 +261,14 @@ static int file_g_read( lua_State* L, int n, int16_t end_char )
end_char = EOF; end_char = EOF;
luaL_Buffer b; luaL_Buffer b;
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
char *p = luaL_prepbuffer(&b); char *p = luaL_prepbuffer(&b);
int i; int i;
n = fs_read(file_fd, p, n); n = vfs_read(file_fd, p, n);
for (i = 0; i < n; ++i) for (i = 0; i < n; ++i)
if (p[i] == end_char) if (p[i] == end_char)
{ {
...@@ -219,7 +281,7 @@ static int file_g_read( lua_State* L, int n, int16_t end_char ) ...@@ -219,7 +281,7 @@ static int file_g_read( lua_State* L, int n, int16_t end_char )
return (lua_objlen(L, -1) > 0); /* check whether read something */ return (lua_objlen(L, -1) > 0); /* check whether read something */
} }
fs_seek(file_fd, -(n - i), SEEK_CUR); vfs_lseek(file_fd, -(n - i), VFS_SEEK_CUR);
luaL_addsize(&b, i); luaL_addsize(&b, i);
luaL_pushresult(&b); /* close buffer */ luaL_pushresult(&b); /* close buffer */
return 1; /* read at least an `eol' */ return 1; /* read at least an `eol' */
...@@ -262,11 +324,11 @@ static int file_readline( lua_State* L ) ...@@ -262,11 +324,11 @@ static int file_readline( lua_State* L )
// Lua: write("string") // Lua: write("string")
static int file_write( lua_State* L ) static int file_write( lua_State* L )
{ {
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
size_t l, rl; size_t l, rl;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
rl = fs_write(file_fd, s, l); rl = vfs_write(file_fd, s, l);
if(rl==l) if(rl==l)
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
else else
...@@ -277,13 +339,13 @@ static int file_write( lua_State* L ) ...@@ -277,13 +339,13 @@ static int file_write( lua_State* L )
// Lua: writeline("string") // Lua: writeline("string")
static int file_writeline( lua_State* L ) static int file_writeline( lua_State* L )
{ {
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
size_t l, rl; size_t l, rl;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
rl = fs_write(file_fd, s, l); rl = vfs_write(file_fd, s, l);
if(rl==l){ if(rl==l){
rl = fs_write(file_fd, "\n", 1); rl = vfs_write(file_fd, "\n", 1);
if(rl==1) if(rl==1)
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
else else
...@@ -295,13 +357,79 @@ static int file_writeline( lua_State* L ) ...@@ -295,13 +357,79 @@ static int file_writeline( lua_State* L )
return 1; return 1;
} }
static int file_fscfg (lua_State *L) // Lua: fsinfo()
static int file_fsinfo( lua_State* L )
{ {
lua_pushinteger (L, fs.cfg.phys_addr); u32_t total, used;
lua_pushinteger (L, fs.cfg.phys_size); if (vfs_fsinfo("", &total, &used)) {
return 2; return luaL_error(L, "file system failed");
}
NODE_DBG("total: %d, used:%d\n", total, used);
if(total>0x7FFFFFFF || used>0x7FFFFFFF || used > total)
{
return luaL_error(L, "file system error");
}
lua_pushinteger(L, total-used);
lua_pushinteger(L, used);
lua_pushinteger(L, total);
return 3;
} }
typedef struct {
vfs_vol *vol;
} volume_type;
// Lua: vol = file.mount("/SD0")
static int file_mount( lua_State *L )
{
const char *ldrv = luaL_checkstring( L, 1 );
int num = luaL_optint( L, 2, -1 );
volume_type *vol = (volume_type *)lua_newuserdata( L, sizeof( volume_type ) );
if (vol->vol = vfs_mount( ldrv, num )) {
/* set its metatable */
luaL_getmetatable(L, "vfs.vol");
lua_setmetatable(L, -2);
return 1;
} else {
// remove created userdata
lua_pop( L, 1 );
return 0;
}
}
// Lua: success = file.chdir("/SD0/")
static int file_chdir( lua_State *L )
{
const char *path = luaL_checkstring( L, 1 );
lua_pushboolean( L, 0 <= vfs_chdir( path ) );
return 1;
}
static int file_vol_umount( lua_State *L )
{
volume_type *vol = luaL_checkudata( L, 1, "file.vol" );
luaL_argcheck( L, vol, 1, "volume expected" );
lua_pushboolean( L, 0 <= vfs_umount( vol->vol ) );
// invalidate vfs descriptor, it has been free'd anyway
vol->vol = NULL;
return 1;
}
static const LUA_REG_TYPE file_vol_map[] =
{
{ LSTRKEY( "umount" ), LFUNCVAL( file_vol_umount )},
//{ LSTRKEY( "getfree" ), LFUNCVAL( file_vol_getfree )},
//{ LSTRKEY( "getlabel" ), LFUNCVAL( file_vol_getlabel )},
//{ LSTRKEY( "__gc" ), LFUNCVAL( file_vol_free ) },
{ LSTRKEY( "__index" ), LROVAL( file_vol_map ) },
{ LNILKEY, LNILVAL }
};
// Module function map // Module function map
static const LUA_REG_TYPE file_map[] = { static const LUA_REG_TYPE file_map[] = {
{ LSTRKEY( "list" ), LFUNCVAL( file_list ) }, { LSTRKEY( "list" ), LFUNCVAL( file_list ) },
...@@ -311,17 +439,27 @@ static const LUA_REG_TYPE file_map[] = { ...@@ -311,17 +439,27 @@ static const LUA_REG_TYPE file_map[] = {
{ LSTRKEY( "writeline" ), LFUNCVAL( file_writeline ) }, { LSTRKEY( "writeline" ), LFUNCVAL( file_writeline ) },
{ LSTRKEY( "read" ), LFUNCVAL( file_read ) }, { LSTRKEY( "read" ), LFUNCVAL( file_read ) },
{ LSTRKEY( "readline" ), LFUNCVAL( file_readline ) }, { LSTRKEY( "readline" ), LFUNCVAL( file_readline ) },
#ifdef BUILD_SPIFFS
{ LSTRKEY( "format" ), LFUNCVAL( file_format ) }, { LSTRKEY( "format" ), LFUNCVAL( file_format ) },
#if defined(BUILD_SPIFFS) { LSTRKEY( "fscfg" ), LFUNCVAL( file_fscfg ) },
#endif
{ LSTRKEY( "remove" ), LFUNCVAL( file_remove ) }, { LSTRKEY( "remove" ), LFUNCVAL( file_remove ) },
{ LSTRKEY( "seek" ), LFUNCVAL( file_seek ) }, { LSTRKEY( "seek" ), LFUNCVAL( file_seek ) },
{ LSTRKEY( "flush" ), LFUNCVAL( file_flush ) }, { LSTRKEY( "flush" ), LFUNCVAL( file_flush ) },
{ LSTRKEY( "rename" ), LFUNCVAL( file_rename ) }, { LSTRKEY( "rename" ), LFUNCVAL( file_rename ) },
{ LSTRKEY( "fsinfo" ), LFUNCVAL( file_fsinfo ) },
{ LSTRKEY( "fscfg" ), LFUNCVAL( file_fscfg ) },
{ LSTRKEY( "exists" ), LFUNCVAL( file_exists ) }, { LSTRKEY( "exists" ), LFUNCVAL( file_exists ) },
{ LSTRKEY( "fsinfo" ), LFUNCVAL( file_fsinfo ) },
{ LSTRKEY( "on" ), LFUNCVAL( file_on ) },
#ifdef BUILD_FATFS
{ LSTRKEY( "mount" ), LFUNCVAL( file_mount ) },
{ LSTRKEY( "chdir" ), LFUNCVAL( file_chdir ) },
#endif #endif
{ LNILKEY, LNILVAL } { LNILKEY, LNILVAL }
}; };
NODEMCU_MODULE(FILE, "file", file_map, NULL); int luaopen_file( lua_State *L ) {
luaL_rometatable( L, "file.vol", (void *)file_vol_map );
return 0;
}
NODEMCU_MODULE(FILE, "file", file_map, luaopen_file);
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "driver/uart.h" #include "driver/uart.h"
#include "user_interface.h" #include "user_interface.h"
#include "flash_api.h" #include "flash_api.h"
#include "flash_fs.h" #include "vfs.h"
#include "user_version.h" #include "user_version.h"
#include "rom.h" #include "rom.h"
#include "task/task.h" #include "task/task.h"
...@@ -226,11 +226,11 @@ static int writer(lua_State* L, const void* p, size_t size, void* u) ...@@ -226,11 +226,11 @@ static int writer(lua_State* L, const void* p, size_t size, void* u)
{ {
UNUSED(L); UNUSED(L);
int file_fd = *( (int *)u ); int file_fd = *( (int *)u );
if ((FS_OPEN_OK - 1) == file_fd) if (!file_fd)
return 1; return 1;
NODE_DBG("get fd:%d,size:%d\n", file_fd, size); NODE_DBG("get fd:%d,size:%d\n", file_fd, size);
if (size != 0 && (size != fs_write(file_fd, (const char *)p, size)) ) if (size != 0 && (size != vfs_write(file_fd, (const char *)p, size)) )
return 1; return 1;
NODE_DBG("write fd:%d,size:%d\n", file_fd, size); NODE_DBG("write fd:%d,size:%d\n", file_fd, size);
return 0; return 0;
...@@ -241,23 +241,26 @@ static int writer(lua_State* L, const void* p, size_t size, void* u) ...@@ -241,23 +241,26 @@ static int writer(lua_State* L, const void* p, size_t size, void* u)
static int node_compile( lua_State* L ) static int node_compile( lua_State* L )
{ {
Proto* f; Proto* f;
int file_fd = FS_OPEN_OK - 1; int file_fd = 0;
size_t len; size_t len;
const char *fname = luaL_checklstring( L, 1, &len ); const char *fname = luaL_checklstring( L, 1, &len );
if ( len >= FS_NAME_MAX_LENGTH ) const char *basename = vfs_basename( fname );
return luaL_error(L, "filename too long"); luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");
char output[FS_NAME_MAX_LENGTH]; char *output = luaM_malloc( L, len+1 );
c_strcpy(output, fname); c_strcpy(output, fname);
// check here that filename end with ".lua". // check here that filename end with ".lua".
if (len < 4 || (c_strcmp( output + len - 4, ".lua") != 0) ) if (len < 4 || (c_strcmp( output + len - 4, ".lua") != 0) ) {
luaM_free( L, output );
return luaL_error(L, "not a .lua file"); return luaL_error(L, "not a .lua file");
}
output[c_strlen(output) - 2] = 'c'; output[c_strlen(output) - 2] = 'c';
output[c_strlen(output) - 1] = '\0'; output[c_strlen(output) - 1] = '\0';
NODE_DBG(output); NODE_DBG(output);
NODE_DBG("\n"); NODE_DBG("\n");
if (luaL_loadfsfile(L, fname) != 0) { if (luaL_loadfsfile(L, fname) != 0) {
luaM_free( L, output );
return luaL_error(L, lua_tostring(L, -1)); return luaL_error(L, lua_tostring(L, -1));
} }
...@@ -265,9 +268,10 @@ static int node_compile( lua_State* L ) ...@@ -265,9 +268,10 @@ static int node_compile( lua_State* L )
int stripping = 1; /* strip debug information? */ int stripping = 1; /* strip debug information? */
file_fd = fs_open(output, fs_mode2flag("w+")); file_fd = vfs_open(output, "w+");
if (file_fd < FS_OPEN_OK) if (!file_fd)
{ {
luaM_free( L, output );
return luaL_error(L, "cannot open/write to file"); return luaL_error(L, "cannot open/write to file");
} }
...@@ -275,12 +279,13 @@ static int node_compile( lua_State* L ) ...@@ -275,12 +279,13 @@ static int node_compile( lua_State* L )
int result = luaU_dump(L, f, writer, &file_fd, stripping); int result = luaU_dump(L, f, writer, &file_fd, stripping);
lua_unlock(L); lua_unlock(L);
if (fs_flush(file_fd) < 0) { // result codes aren't propagated by flash_fs.h if (vfs_flush(file_fd) != VFS_RES_OK) {
// overwrite Lua error, like writer() does in case of a file io error // overwrite Lua error, like writer() does in case of a file io error
result = 1; result = 1;
} }
fs_close(file_fd); vfs_close(file_fd);
file_fd = FS_OPEN_OK - 1; file_fd = 0;
luaM_free( L, output );
if (result == LUA_ERR_CC_INTOVERFLOW) { if (result == LUA_ERR_CC_INTOVERFLOW) {
return luaL_error(L, "value too big or small for target integer type"); return luaL_error(L, "value too big or small for target integer type");
......
#include "flash_fs.h"
#include "c_string.h"
#include "spiffs.h"
int fs_mode2flag(const char *mode){
if(c_strlen(mode)==1){
if(c_strcmp(mode,"w")==0)
return FS_WRONLY|FS_CREAT|FS_TRUNC;
else if(c_strcmp(mode, "r")==0)
return FS_RDONLY;
else if(c_strcmp(mode, "a")==0)
return FS_WRONLY|FS_CREAT|FS_APPEND;
else
return FS_RDONLY;
} else if (c_strlen(mode)==2){
if(c_strcmp(mode,"r+")==0)
return FS_RDWR;
else if(c_strcmp(mode, "w+")==0)
return FS_RDWR|FS_CREAT|FS_TRUNC;
else if(c_strcmp(mode, "a+")==0)
return FS_RDWR|FS_CREAT|FS_APPEND;
else
return FS_RDONLY;
} else {
return FS_RDONLY;
}
}
#ifndef __FLASH_FS_H__
#define __FLASH_FS_H__
#include "user_config.h"
#if defined( BUILD_SPIFFS )
#include "myspiffs.h"
#define FS_OPEN_OK 1
#define FS_RDONLY SPIFFS_RDONLY
#define FS_WRONLY SPIFFS_WRONLY
#define FS_RDWR SPIFFS_RDWR
#define FS_APPEND SPIFFS_APPEND
#define FS_TRUNC SPIFFS_TRUNC
#define FS_CREAT SPIFFS_CREAT
#define FS_EXCL SPIFFS_EXCL
#define FS_SEEK_SET SPIFFS_SEEK_SET
#define FS_SEEK_CUR SPIFFS_SEEK_CUR
#define FS_SEEK_END SPIFFS_SEEK_END
#define fs_open myspiffs_open
#define fs_close myspiffs_close
#define fs_write myspiffs_write
#define fs_read myspiffs_read
#define fs_seek myspiffs_lseek
#define fs_eof myspiffs_eof
#define fs_getc myspiffs_getc
#define fs_ungetc myspiffs_ungetc
#define fs_flush myspiffs_flush
#define fs_error myspiffs_error
#define fs_clearerr myspiffs_clearerr
#define fs_tell myspiffs_tell
#define fs_format myspiffs_format
#define fs_check myspiffs_check
#define fs_rename myspiffs_rename
#define fs_size myspiffs_size
#define fs_mount myspiffs_mount
#define fs_unmount myspiffs_unmount
#define FS_NAME_MAX_LENGTH SPIFFS_OBJ_NAME_LEN
#endif
int fs_mode2flag(const char *mode);
#endif // #ifndef __FLASH_FS_H__
...@@ -671,7 +671,7 @@ int platform_i2c_recv_byte( unsigned id, int ack ){ ...@@ -671,7 +671,7 @@ int platform_i2c_recv_byte( unsigned id, int ack ){
// ***************************************************************************** // *****************************************************************************
// SPI platform interface // SPI platform interface
uint32_t platform_spi_setup( uint8_t id, int mode, unsigned cpol, unsigned cpha, uint32_t clock_div) uint32_t platform_spi_setup( uint8_t id, int mode, unsigned cpol, unsigned cpha, uint32_t clock_div )
{ {
spi_master_init( id, cpol, cpha, clock_div ); spi_master_init( id, cpol, cpha, clock_div );
return 1; return 1;
...@@ -696,6 +696,49 @@ spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type ...@@ -696,6 +696,49 @@ spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type
return spi_mast_get_miso( id, 0, bitlen ); return spi_mast_get_miso( id, 0, bitlen );
} }
int platform_spi_blkwrite( uint8_t id, size_t len, const uint8_t *data )
{
spi_mast_byte_order( id, SPI_ORDER_LSB );
while (len > 0) {
size_t chunk_len = len > 64 ? 64 : len;
spi_mast_blkset( id, chunk_len * 8, data );
spi_mast_transaction( id, 0, 0, 0, 0, chunk_len * 8, 0, 0 );
data = &(data[chunk_len]);
len -= chunk_len;
}
spi_mast_byte_order( id, SPI_ORDER_MSB );
return PLATFORM_OK;
}
int platform_spi_blkread( uint8_t id, size_t len, uint8_t *data )
{
uint8_t mosi_idle[64];
os_memset( (void *)mosi_idle, 0xff, len > 64 ? 64 : len );
spi_mast_byte_order( id, SPI_ORDER_LSB );
while (len > 0 ) {
size_t chunk_len = len > 64 ? 64 : len;
spi_mast_blkset( id, chunk_len * 8, mosi_idle );
spi_mast_transaction( id, 0, 0, 0, 0, chunk_len * 8, 0, -1 );
spi_mast_blkget( id, chunk_len * 8, data );
data = &(data[chunk_len]);
len -= chunk_len;
}
spi_mast_byte_order( id, SPI_ORDER_MSB );
return PLATFORM_OK;
}
int platform_spi_set_mosi( uint8_t id, uint16_t offset, uint8_t bitlen, spi_data_type data ) int platform_spi_set_mosi( uint8_t id, uint16_t offset, uint8_t bitlen, spi_data_type data )
{ {
if (offset + bitlen > 512) if (offset + bitlen > 512)
......
...@@ -110,6 +110,8 @@ int platform_spi_send( uint8_t id, uint8_t bitlen, spi_data_type data ); ...@@ -110,6 +110,8 @@ int platform_spi_send( uint8_t id, uint8_t bitlen, spi_data_type data );
spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type data ); spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type data );
void platform_spi_select( unsigned id, int is_select ); void platform_spi_select( unsigned id, int is_select );
int platform_spi_blkwrite( uint8_t id, size_t len, const uint8_t *data );
int platform_spi_blkread( uint8_t id, size_t len, uint8_t *data );
int platform_spi_set_mosi( uint8_t id, uint16_t offset, uint8_t bitlen, spi_data_type data ); int platform_spi_set_mosi( uint8_t id, uint16_t offset, uint8_t bitlen, spi_data_type data );
spi_data_type platform_spi_get_miso( uint8_t id, uint16_t offset, uint8_t bitlen ); spi_data_type platform_spi_get_miso( uint8_t id, uint16_t offset, uint8_t bitlen );
int platform_spi_transaction( uint8_t id, uint8_t cmd_bitlen, spi_data_type cmd_data, int platform_spi_transaction( uint8_t id, uint8_t cmd_bitlen, spi_data_type cmd_data,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment