Commit fa7cf878 authored by zeroday's avatar zeroday
Browse files

Merge pull request #287 from nodemcu/dev

Dev merge to master
parents 6c8cace9 1652df50
...@@ -39,7 +39,9 @@ endif ...@@ -39,7 +39,9 @@ endif
INCLUDES := $(INCLUDES) -I $(PDIR)include INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./ INCLUDES += -I ./
INCLUDES += -I ../libc INCLUDES += -I ../libc
INCLUDES += -I ../coap
INCLUDES += -I ../mqtt INCLUDES += -I ../mqtt
INCLUDES += -I ../u8glib
INCLUDES += -I ../lua INCLUDES += -I ../lua
INCLUDES += -I ../platform INCLUDES += -I ../platform
INCLUDES += -I ../wofs INCLUDES += -I ../wofs
......
...@@ -61,9 +61,15 @@ LUALIB_API int ( luaopen_i2c )( lua_State *L ); ...@@ -61,9 +61,15 @@ LUALIB_API int ( luaopen_i2c )( lua_State *L );
#define AUXLIB_WIFI "wifi" #define AUXLIB_WIFI "wifi"
LUALIB_API int ( luaopen_wifi )( lua_State *L ); LUALIB_API int ( luaopen_wifi )( lua_State *L );
#define AUXLIB_COAP "coap"
LUALIB_API int ( luaopen_coap )( lua_State *L );
#define AUXLIB_MQTT "mqtt" #define AUXLIB_MQTT "mqtt"
LUALIB_API int ( luaopen_mqtt )( lua_State *L ); LUALIB_API int ( luaopen_mqtt )( lua_State *L );
#define AUXLIB_U8G "u8g"
LUALIB_API int ( luaopen_u8g )( lua_State *L );
#define AUXLIB_NODE "node" #define AUXLIB_NODE "node"
LUALIB_API int ( luaopen_node )( lua_State *L ); LUALIB_API int ( luaopen_node )( lua_State *L );
...@@ -92,5 +98,9 @@ LUALIB_API int ( luaopen_ow )( lua_State *L ); ...@@ -92,5 +98,9 @@ LUALIB_API int ( luaopen_ow )( lua_State *L );
lua_pushnumber( L, val );\ lua_pushnumber( L, val );\
lua_setfield( L, -2, name ) lua_setfield( L, -2, name )
#define MOD_REG_LUDATA( L, name, val )\
lua_pushlightuserdata( L, val );\
lua_setfield( L, -2, name )
#endif #endif
// Module for coapwork
//#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "platform.h"
#include "auxmods.h"
#include "lrotable.h"
#include "c_string.h"
#include "c_stdlib.h"
#include "c_types.h"
#include "mem.h"
#include "espconn.h"
#include "driver/uart.h"
#include "coap.h"
#include "uri.h"
#include "node.h"
#include "coap_timer.h"
#include "coap_io.h"
#include "coap_server.h"
coap_queue_t *gQueue = NULL;
typedef struct lcoap_userdata
{
lua_State *L;
struct espconn *pesp_conn;
int self_ref;
}lcoap_userdata;
static void coap_received(void *arg, char *pdata, unsigned short len)
{
NODE_DBG("coap_received is called.\n");
struct espconn *pesp_conn = arg;
lcoap_userdata *cud = (lcoap_userdata *)pesp_conn->reverse;
// static uint8_t buf[MAX_MESSAGE_SIZE+1] = {0}; // +1 for string '\0'
uint8_t buf[MAX_MESSAGE_SIZE+1] = {0}; // +1 for string '\0'
c_memset(buf, 0, sizeof(buf)); // wipe prev data
if (len > MAX_MESSAGE_SIZE) {
NODE_DBG("Request Entity Too Large.\n"); // NOTE: should response 4.13 to client...
return;
}
// c_memcpy(buf, pdata, len);
size_t rsplen = coap_server_respond(pdata, len, buf, MAX_MESSAGE_SIZE+1);
espconn_sent(pesp_conn, (unsigned char *)buf, rsplen);
// c_memset(buf, 0, sizeof(buf));
}
static void coap_sent(void *arg)
{
NODE_DBG("coap_sent is called.\n");
}
// Lua: s = coap.create(function(conn))
static int coap_create( lua_State* L, const char* mt )
{
struct espconn *pesp_conn = NULL;
lcoap_userdata *cud;
unsigned type;
int stack = 1;
// create a object
cud = (lcoap_userdata *)lua_newuserdata(L, sizeof(lcoap_userdata));
// pre-initialize it, in case of errors
cud->self_ref = LUA_NOREF;
cud->pesp_conn = NULL;
// set its metatable
luaL_getmetatable(L, mt);
lua_setmetatable(L, -2);
// create the espconn struct
pesp_conn = (struct espconn *)c_zalloc(sizeof(struct espconn));
if(!pesp_conn)
return luaL_error(L, "not enough memory");
cud->pesp_conn = pesp_conn;
pesp_conn->type = ESPCONN_UDP;
pesp_conn->proto.tcp = NULL;
pesp_conn->proto.udp = NULL;
pesp_conn->proto.udp = (esp_udp *)c_zalloc(sizeof(esp_udp));
if(!pesp_conn->proto.udp){
c_free(pesp_conn);
cud->pesp_conn = pesp_conn = NULL;
return luaL_error(L, "not enough memory");
}
pesp_conn->state = ESPCONN_NONE;
NODE_DBG("UDP server/client is set.\n");
cud->L = L;
pesp_conn->reverse = cud;
NODE_DBG("coap_create is called.\n");
return 1;
}
// Lua: server:delete()
static int coap_delete( lua_State* L, const char* mt )
{
struct espconn *pesp_conn = NULL;
lcoap_userdata *cud;
cud = (lcoap_userdata *)luaL_checkudata(L, 1, mt);
luaL_argcheck(L, cud, 1, "Server/Client expected");
if(cud==NULL){
NODE_DBG("userdata is nil.\n");
return 0;
}
// free (unref) callback ref
if(LUA_NOREF!=cud->self_ref){
luaL_unref(L, LUA_REGISTRYINDEX, cud->self_ref);
cud->self_ref = LUA_NOREF;
}
cud->L = NULL;
if(cud->pesp_conn)
{
if(cud->pesp_conn->proto.udp->remote_port || cud->pesp_conn->proto.udp->local_port)
espconn_delete(cud->pesp_conn);
c_free(cud->pesp_conn->proto.udp);
cud->pesp_conn->proto.udp = NULL;
c_free(cud->pesp_conn);
cud->pesp_conn = NULL;
}
NODE_DBG("coap_delete is called.\n");
return 0;
}
// Lua: server:listen( port, ip )
static int coap_start( lua_State* L, const char* mt )
{
struct espconn *pesp_conn = NULL;
lcoap_userdata *cud;
unsigned port;
size_t il;
ip_addr_t ipaddr;
cud = (lcoap_userdata *)luaL_checkudata(L, 1, mt);
luaL_argcheck(L, cud, 1, "Server/Client expected");
if(cud==NULL){
NODE_DBG("userdata is nil.\n");
return 0;
}
pesp_conn = cud->pesp_conn;
port = luaL_checkinteger( L, 2 );
pesp_conn->proto.udp->local_port = port;
NODE_DBG("UDP port is set: %d.\n", port);
if( lua_isstring(L,3) ) // deal with the ip string
{
const char *ip = luaL_checklstring( L, 3, &il );
if (ip == NULL)
{
ip = "0.0.0.0";
}
ipaddr.addr = ipaddr_addr(ip);
c_memcpy(pesp_conn->proto.udp->local_ip, &ipaddr.addr, 4);
NODE_DBG("UDP ip is set: ");
NODE_DBG(IPSTR, IP2STR(&ipaddr.addr));
NODE_DBG("\n");
}
if(LUA_NOREF==cud->self_ref){
lua_pushvalue(L, 1); // copy to the top of stack
cud->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
espconn_regist_recvcb(pesp_conn, coap_received);
espconn_regist_sentcb(pesp_conn, coap_sent);
espconn_create(pesp_conn);
NODE_DBG("Coap Server started on port: %d\n", port);
NODE_DBG("coap_start is called.\n");
return 0;
}
// Lua: server:close()
static int coap_close( lua_State* L, const char* mt )
{
struct espconn *pesp_conn = NULL;
lcoap_userdata *cud;
cud = (lcoap_userdata *)luaL_checkudata(L, 1, mt);
luaL_argcheck(L, cud, 1, "Server/Client expected");
if(cud==NULL){
NODE_DBG("userdata is nil.\n");
return 0;
}
if(cud->pesp_conn)
{
if(cud->pesp_conn->proto.udp->remote_port || cud->pesp_conn->proto.udp->local_port)
espconn_delete(cud->pesp_conn);
}
if(LUA_NOREF!=cud->self_ref){
luaL_unref(L, LUA_REGISTRYINDEX, cud->self_ref);
cud->self_ref = LUA_NOREF;
}
NODE_DBG("coap_close is called.\n");
return 0;
}
// Lua: server/client:on( "method", function(s) )
static int coap_on( lua_State* L, const char* mt )
{
NODE_DBG("coap_on is called.\n");
return 0;
}
static void coap_response_handler(void *arg, char *pdata, unsigned short len)
{
NODE_DBG("coap_response_handler is called.\n");
struct espconn *pesp_conn = arg;
coap_packet_t pkt;
pkt.content.p = NULL;
pkt.content.len = 0;
// static uint8_t buf[MAX_MESSAGE_SIZE+1] = {0}; // +1 for string '\0'
uint8_t buf[MAX_MESSAGE_SIZE+1] = {0}; // +1 for string '\0'
c_memset(buf, 0, sizeof(buf)); // wipe prev data
int rc;
if( len > MAX_MESSAGE_SIZE )
{
NODE_DBG("Request Entity Too Large.\n"); // NOTE: should response 4.13 to client...
return;
}
c_memcpy(buf, pdata, len);
if (0 != (rc = coap_parse(&pkt, buf, len))){
NODE_DBG("Bad packet rc=%d\n", rc);
}
else
{
#ifdef COAP_DEBUG
coap_dumpPacket(&pkt);
#endif
/* check if this is a response to our original request */
if (!check_token(&pkt)) {
/* drop if this was just some message, or send RST in case of notification */
if (pkt.hdr.t == COAP_TYPE_CON || pkt.hdr.t == COAP_TYPE_NONCON){
// coap_send_rst(pkt); // send RST response
// or, just ignore it.
}
goto end;
}
if (pkt.hdr.t == COAP_TYPE_RESET) {
NODE_DBG("got RST\n");
goto end;
}
uint32_t ip = 0, port = 0;
coap_tid_t id = COAP_INVALID_TID;
c_memcpy(&ip, pesp_conn->proto.udp->remote_ip, sizeof(ip));
port = pesp_conn->proto.udp->remote_port;
coap_transaction_id(ip, port, &pkt, &id);
/* transaction done, remove the node from queue */
// stop timer
coap_timer_stop();
// remove the node
coap_remove_node(&gQueue, id);
// calculate time elapsed
coap_timer_update(&gQueue);
coap_timer_start(&gQueue);
if (COAP_RESPONSE_CLASS(pkt.hdr.code) == 2)
{
/* There is no block option set, just read the data and we are done. */
NODE_DBG("%d.%02d\t", (pkt.hdr.code >> 5), pkt.hdr.code & 0x1F);
NODE_DBG((char *)pkt.payload.p);
}
else if (COAP_RESPONSE_CLASS(pkt.hdr.code) >= 4)
{
NODE_DBG("%d.%02d\t", (pkt.hdr.code >> 5), pkt.hdr.code & 0x1F);
NODE_DBG((char *)pkt.payload.p);
}
}
end:
if(!gQueue){ // if there is no node pending in the queue, disconnect from host.
if(pesp_conn->proto.udp->remote_port || pesp_conn->proto.udp->local_port)
espconn_delete(pesp_conn);
}
// c_memset(buf, 0, sizeof(buf));
}
// Lua: client:request( [CON], uri, [payload] )
static int coap_request( lua_State* L, coap_method_t m )
{
struct espconn *pesp_conn = NULL;
lcoap_userdata *cud;
int stack = 1;
cud = (lcoap_userdata *)luaL_checkudata(L, stack, "coap_client");
luaL_argcheck(L, cud, stack, "Server/Client expected");
if(cud==NULL){
NODE_DBG("userdata is nil.\n");
return 0;
}
stack++;
pesp_conn = cud->pesp_conn;
ip_addr_t ipaddr;
uint8_t host[32];
unsigned t;
if ( lua_isnumber(L, stack) )
{
t = lua_tointeger(L, stack);
stack++;
if ( t != COAP_TYPE_CON && t != COAP_TYPE_NONCON )
return luaL_error( L, "wrong arg type" );
} else {
t = COAP_TYPE_CON; // default to CON
}
size_t l;
const char *url = luaL_checklstring( L, stack, &l );
stack++;
if (url == NULL)
return luaL_error( L, "wrong arg type" );
coap_uri_t *uri = coap_new_uri(url, l); // should call free(uri) somewhere
if (uri == NULL)
return luaL_error( L, "uri wrong format." );
pesp_conn->proto.udp->remote_port = uri->port;
NODE_DBG("UDP port is set: %d.\n", uri->port);
pesp_conn->proto.udp->local_port = espconn_port();
if(uri->host.length){
c_memcpy(host, uri->host.s, uri->host.length);
host[uri->host.length] = '\0';
ipaddr.addr = ipaddr_addr(host);
NODE_DBG("Host len(%d):", uri->host.length);
NODE_DBG(host);
NODE_DBG("\n");
c_memcpy(pesp_conn->proto.udp->remote_ip, &ipaddr.addr, 4);
NODE_DBG("UDP ip is set: ");
NODE_DBG(IPSTR, IP2STR(&ipaddr.addr));
NODE_DBG("\n");
}
coap_pdu_t *pdu = coap_new_pdu(); // should call coap_delete_pdu() somewhere
if(!pdu){
if(uri)
c_free(uri);
return;
}
const char *payload = NULL;
l = 0;
if( lua_isstring(L, stack) ){
payload = luaL_checklstring( L, stack, &l );
if (payload == NULL)
l = 0;
}
coap_make_request(&(pdu->scratch), pdu->pkt, t, m, uri, payload, l);
#ifdef COAP_DEBUG
coap_dumpPacket(pdu->pkt);
#endif
int rc;
if (0 != (rc = coap_build(pdu->msg.p, &(pdu->msg.len), pdu->pkt))){
NODE_DBG("coap_build failed rc=%d\n", rc);
}
else
{
#ifdef COAP_DEBUG
NODE_DBG("Sending: ");
coap_dump(pdu->msg.p, pdu->msg.len, true);
NODE_DBG("\n");
#endif
espconn_regist_recvcb(pesp_conn, coap_response_handler);
sint8_t con = espconn_create(pesp_conn);
if( ESPCONN_OK != con){
NODE_DBG("Connect to host. code:%d\n", con);
// coap_delete_pdu(pdu);
}
// else
{
coap_tid_t tid = COAP_INVALID_TID;
if (pdu->pkt->hdr.t == COAP_TYPE_CON){
tid = coap_send_confirmed(pesp_conn, pdu);
}
else {
tid = coap_send(pesp_conn, pdu);
}
if (pdu->pkt->hdr.t != COAP_TYPE_CON || tid == COAP_INVALID_TID){
coap_delete_pdu(pdu);
}
}
}
if(uri)
c_free((void *)uri);
NODE_DBG("coap_request is called.\n");
return 0;
}
extern coap_luser_entry *variable_entry;
extern coap_luser_entry *function_entry;
// Lua: coap:var/func( string )
static int coap_regist( lua_State* L, const char* mt, int isvar )
{
size_t l;
const char *name = luaL_checklstring( L, 2, &l );
if (name == NULL)
return luaL_error( L, "name must be set." );
coap_luser_entry *h = NULL;
// if(lua_isstring(L, 3))
if(isvar)
h = variable_entry;
else
h = function_entry;
while(NULL!=h->next){ // goto the end of the list
if(h->name!= NULL && c_strcmp(h->name, name)==0) // key exist, override it
break;
h = h->next;
}
if(h->name==NULL || c_strcmp(h->name, name)!=0){ // not exists. make a new one.
h->next = (coap_luser_entry *)c_zalloc(sizeof(coap_luser_entry));
h = h->next;
if(h == NULL)
return luaL_error(L, "not enough memory");
h->next = NULL;
h->name = NULL;
h->L = NULL;
}
h->L = L;
h->name = name;
NODE_DBG("coap_regist is called.\n");
return 0;
}
// Lua: s = coap.createServer(function(conn))
static int coap_createServer( lua_State* L )
{
const char *mt = "coap_server";
return coap_create(L, mt);
}
// Lua: server:delete()
static int coap_server_delete( lua_State* L )
{
const char *mt = "coap_server";
return coap_delete(L, mt);
}
// Lua: server:listen( port, ip, function(err) )
static int coap_server_listen( lua_State* L )
{
const char *mt = "coap_server";
return coap_start(L, mt);
}
// Lua: server:close()
static int coap_server_close( lua_State* L )
{
const char *mt = "coap_server";
return coap_close(L, mt);
}
// Lua: server:on( "method", function(server) )
static int coap_server_on( lua_State* L )
{
const char *mt = "coap_server";
return coap_on(L, mt);
}
// Lua: server:var( "name" )
static int coap_server_var( lua_State* L )
{
const char *mt = "coap_server";
return coap_regist(L, mt, 1);
}
// Lua: server:func( "name" )
static int coap_server_func( lua_State* L )
{
const char *mt = "coap_server";
return coap_regist(L, mt, 0);
}
// Lua: s = coap.createClient(function(conn))
static int coap_createClient( lua_State* L )
{
const char *mt = "coap_client";
return coap_create(L, mt);
}
// Lua: client:gcdelete()
static int coap_client_gcdelete( lua_State* L )
{
const char *mt = "coap_client";
return coap_delete(L, mt);
}
// client:get( string, function(sent) )
static int coap_client_get( lua_State* L )
{
return coap_request(L, COAP_METHOD_GET);
}
// client:post( string, function(sent) )
static int coap_client_post( lua_State* L )
{
return coap_request(L, COAP_METHOD_POST);
}
// client:put( string, function(sent) )
static int coap_client_put( lua_State* L )
{
return coap_request(L, COAP_METHOD_PUT);
}
// client:delete( string, function(sent) )
static int coap_client_delete( lua_State* L )
{
return coap_request(L, COAP_METHOD_DELETE);
}
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
static const LUA_REG_TYPE coap_server_map[] =
{
{ LSTRKEY( "listen" ), LFUNCVAL ( coap_server_listen ) },
{ LSTRKEY( "close" ), LFUNCVAL ( coap_server_close ) },
{ LSTRKEY( "var" ), LFUNCVAL ( coap_server_var ) },
{ LSTRKEY( "func" ), LFUNCVAL ( coap_server_func ) },
{ LSTRKEY( "__gc" ), LFUNCVAL ( coap_server_delete ) },
#if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "__index" ), LROVAL ( coap_server_map ) },
#endif
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE coap_client_map[] =
{
{ LSTRKEY( "get" ), LFUNCVAL ( coap_client_get ) },
{ LSTRKEY( "post" ), LFUNCVAL ( coap_client_post ) },
{ LSTRKEY( "put" ), LFUNCVAL ( coap_client_put ) },
{ LSTRKEY( "delete" ), LFUNCVAL ( coap_client_delete ) },
{ LSTRKEY( "__gc" ), LFUNCVAL ( coap_client_gcdelete ) },
#if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "__index" ), LROVAL ( coap_client_map ) },
#endif
{ LNILKEY, LNILVAL }
};
const LUA_REG_TYPE coap_map[] =
{
{ LSTRKEY( "Server" ), LFUNCVAL ( coap_createServer ) },
{ LSTRKEY( "Client" ), LFUNCVAL ( coap_createClient ) },
#if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "CON" ), LNUMVAL( COAP_TYPE_CON ) },
{ LSTRKEY( "NON" ), LNUMVAL( COAP_TYPE_NONCON ) },
{ LSTRKEY( "__metatable" ), LROVAL( coap_map ) },
#endif
{ LNILKEY, LNILVAL }
};
LUALIB_API int luaopen_coap( lua_State *L )
{
endpoint_setup();
#if LUA_OPTIMIZE_MEMORY > 0
luaL_rometatable(L, "coap_server", (void *)coap_server_map); // create metatable for coap_server
luaL_rometatable(L, "coap_client", (void *)coap_client_map); // create metatable for coap_client
return 0;
#else // #if LUA_OPTIMIZE_MEMORY > 0
int n;
luaL_register( L, AUXLIB_COAP, coap_map );
// Set it as its own metatable
lua_pushvalue( L, -1 );
lua_setmetatable( L, -2 );
// Module constants
MOD_REG_NUMBER( L, "CON", COAP_TYPE_CON );
MOD_REG_NUMBER( L, "NON", COAP_TYPE_NONCON );
n = lua_gettop(L);
// create metatable
luaL_newmetatable(L, "coap_server");
// metatable.__index = metatable
lua_pushliteral(L, "__index");
lua_pushvalue(L,-2);
lua_rawset(L,-3);
// Setup the methods inside metatable
luaL_register( L, NULL, coap_server_map );
lua_settop(L, n);
// create metatable
luaL_newmetatable(L, "coap_client");
// metatable.__index = metatable
lua_pushliteral(L, "__index");
lua_pushvalue(L,-2);
lua_rawset(L,-3);
// Setup the methods inside metatable
luaL_register( L, NULL, coap_client_map );
return 1;
#endif // #if LUA_OPTIMIZE_MEMORY > 0
}
...@@ -111,7 +111,7 @@ static int file_seek (lua_State *L) ...@@ -111,7 +111,7 @@ static int file_seek (lua_State *L)
long offset = luaL_optlong(L, 2, 0); long offset = luaL_optlong(L, 2, 0);
op = fs_seek(file_fd, offset, mode[op]); op = fs_seek(file_fd, offset, mode[op]);
if (op) if (op)
lua_pushboolean(L, 1); /* error */ lua_pushnil(L); /* error */
else else
lua_pushinteger(L, fs_tell(file_fd)); lua_pushinteger(L, fs_tell(file_fd));
return 1; return 1;
...@@ -175,6 +175,22 @@ static int file_rename( lua_State* L ) ...@@ -175,6 +175,22 @@ static int file_rename( lua_State* L )
return 1; return 1;
} }
// Lua: fsinfo()
static int file_fsinfo( lua_State* L )
{
uint32_t total, used;
SPIFFS_info(&fs, &total, &used);
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 #endif
// g_read() // g_read()
...@@ -308,6 +324,7 @@ const LUA_REG_TYPE file_map[] = ...@@ -308,6 +324,7 @@ const LUA_REG_TYPE file_map[] =
{ LSTRKEY( "flush" ), LFUNCVAL( file_flush ) }, { LSTRKEY( "flush" ), LFUNCVAL( file_flush ) },
// { LSTRKEY( "check" ), LFUNCVAL( file_check ) }, // { LSTRKEY( "check" ), LFUNCVAL( file_check ) },
{ LSTRKEY( "rename" ), LFUNCVAL( file_rename ) }, { LSTRKEY( "rename" ), LFUNCVAL( file_rename ) },
{ LSTRKEY( "fsinfo" ), LFUNCVAL( file_fsinfo ) },
#endif #endif
#if LUA_OPTIMIZE_MEMORY > 0 #if LUA_OPTIMIZE_MEMORY > 0
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include "lrotable.h" #include "lrotable.h"
#include "luaconf.h" #include "luaconf.h"
#include "user_modules.h"
#if defined(LUA_USE_MODULES) #if defined(LUA_USE_MODULES)
#include "modules.h" #include "modules.h"
#endif #endif
...@@ -28,12 +30,26 @@ LUA_MODULES_ROM ...@@ -28,12 +30,26 @@ LUA_MODULES_ROM
static const luaL_Reg lualibs[] = { static const luaL_Reg lualibs[] = {
{"", luaopen_base}, {"", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package}, {LUA_LOADLIBNAME, luaopen_package},
// {LUA_IOLIBNAME, luaopen_io}, #if defined(LUA_USE_BUILTIN_IO)
{LUA_IOLIBNAME, luaopen_io},
#endif
#if defined(LUA_USE_BUILTIN_STRING)
{LUA_STRLIBNAME, luaopen_string}, {LUA_STRLIBNAME, luaopen_string},
#endif
#if LUA_OPTIMIZE_MEMORY == 0 #if LUA_OPTIMIZE_MEMORY == 0
// {LUA_MATHLIBNAME, luaopen_math}, #if defined(LUA_USE_BUILTIN_MATH)
{LUA_MATHLIBNAME, luaopen_math},
#endif
#if defined(LUA_USE_BUILTIN_TABLE)
{LUA_TABLIBNAME, luaopen_table}, {LUA_TABLIBNAME, luaopen_table},
// {LUA_DBLIBNAME, luaopen_debug}, #endif
#if defined(LUA_USE_BUILTIN_DEBUG)
{LUA_DBLIBNAME, luaopen_debug},
#endif
#endif #endif
#if defined(LUA_MODULES_ROM) #if defined(LUA_MODULES_ROM)
#undef _ROM #undef _ROM
...@@ -43,12 +59,30 @@ static const luaL_Reg lualibs[] = { ...@@ -43,12 +59,30 @@ static const luaL_Reg lualibs[] = {
{NULL, NULL} {NULL, NULL}
}; };
#if defined(LUA_USE_BUILTIN_STRING)
extern const luaR_entry strlib[]; extern const luaR_entry strlib[];
#endif
#if defined(LUA_USE_BUILTIN_OS)
extern const luaR_entry syslib[]; extern const luaR_entry syslib[];
#endif
#if defined(LUA_USE_BUILTIN_TABLE)
extern const luaR_entry tab_funcs[]; extern const luaR_entry tab_funcs[];
// extern const luaR_entry dblib[]; #endif
#if defined(LUA_USE_BUILTIN_DEBUG)
extern const luaR_entry dblib[];
#endif
#if defined(LUA_USE_BUILTIN_COROUTINE)
extern const luaR_entry co_funcs[]; extern const luaR_entry co_funcs[];
// extern const luaR_entry math_map[]; #endif
#if defined(LUA_USE_BUILTIN_MATH)
extern const luaR_entry math_map[];
#endif
#if defined(LUA_MODULES_ROM) && LUA_OPTIMIZE_MEMORY == 2 #if defined(LUA_MODULES_ROM) && LUA_OPTIMIZE_MEMORY == 2
#undef _ROM #undef _ROM
#define _ROM( name, openf, table ) extern const luaR_entry table[]; #define _ROM( name, openf, table ) extern const luaR_entry table[];
...@@ -57,11 +91,30 @@ LUA_MODULES_ROM ...@@ -57,11 +91,30 @@ LUA_MODULES_ROM
const luaR_table lua_rotable[] = const luaR_table lua_rotable[] =
{ {
#if LUA_OPTIMIZE_MEMORY > 0 #if LUA_OPTIMIZE_MEMORY > 0
#if defined(LUA_USE_BUILTIN_STRING)
{LUA_STRLIBNAME, strlib}, {LUA_STRLIBNAME, strlib},
#endif
#if defined(LUA_USE_BUILTIN_TABLE)
{LUA_TABLIBNAME, tab_funcs}, {LUA_TABLIBNAME, tab_funcs},
// {LUA_DBLIBNAME, dblib}, #endif
#if defined(LUA_USE_BUILTIN_DEBUG)
{LUA_DBLIBNAME, dblib},
#endif
#if defined(LUA_USE_BUILTIN_COROUTINE)
{LUA_COLIBNAME, co_funcs}, {LUA_COLIBNAME, co_funcs},
// {LUA_MATHLIBNAME, math_map}, #endif
#if defined(LUA_USE_BUILTIN_MATH)
{LUA_MATHLIBNAME, math_map},
#endif
#if defined(LUA_USE_BUILTIN_OS)
{LUA_OSLIBNAME, syslib},
#endif
#if defined(LUA_MODULES_ROM) && LUA_OPTIMIZE_MEMORY == 2 #if defined(LUA_MODULES_ROM) && LUA_OPTIMIZE_MEMORY == 2
#undef _ROM #undef _ROM
#define _ROM( name, openf, table ) { name, table }, #define _ROM( name, openf, table ) { name, table },
......
...@@ -37,6 +37,14 @@ ...@@ -37,6 +37,14 @@
#define ROM_MODULES_NET #define ROM_MODULES_NET
#endif #endif
#if defined(LUA_USE_MODULES_COAP)
#define MODULES_COAP "coap"
#define ROM_MODULES_COAP \
_ROM(MODULES_COAP, luaopen_coap, coap_map)
#else
#define ROM_MODULES_COAP
#endif
#if defined(LUA_USE_MODULES_MQTT) #if defined(LUA_USE_MODULES_MQTT)
#define MODULES_MQTT "mqtt" #define MODULES_MQTT "mqtt"
#define ROM_MODULES_MQTT \ #define ROM_MODULES_MQTT \
...@@ -45,6 +53,14 @@ ...@@ -45,6 +53,14 @@
#define ROM_MODULES_MQTT #define ROM_MODULES_MQTT
#endif #endif
#if defined(LUA_USE_MODULES_U8G)
#define MODULES_U8G "u8g"
#define ROM_MODULES_U8G \
_ROM(MODULES_U8G, luaopen_u8g, lu8g_map)
#else
#define ROM_MODULES_U8G
#endif
#if defined(LUA_USE_MODULES_I2C) #if defined(LUA_USE_MODULES_I2C)
#define MODULES_I2C "i2c" #define MODULES_I2C "i2c"
#define ROM_MODULES_I2C \ #define ROM_MODULES_I2C \
...@@ -130,7 +146,9 @@ ...@@ -130,7 +146,9 @@
ROM_MODULES_GPIO \ ROM_MODULES_GPIO \
ROM_MODULES_PWM \ ROM_MODULES_PWM \
ROM_MODULES_WIFI \ ROM_MODULES_WIFI \
ROM_MODULES_COAP \
ROM_MODULES_MQTT \ ROM_MODULES_MQTT \
ROM_MODULES_U8G \
ROM_MODULES_I2C \ ROM_MODULES_I2C \
ROM_MODULES_SPI \ ROM_MODULES_SPI \
ROM_MODULES_TMR \ ROM_MODULES_TMR \
......
...@@ -1102,7 +1102,7 @@ const LUA_REG_TYPE mqtt_map[] = ...@@ -1102,7 +1102,7 @@ const LUA_REG_TYPE mqtt_map[] =
{ LNILKEY, LNILVAL } { LNILKEY, LNILVAL }
}; };
LUALIB_API int ICACHE_FLASH_ATTR luaopen_mqtt( lua_State *L ) LUALIB_API int luaopen_mqtt( lua_State *L )
{ {
#if LUA_OPTIMIZE_MEMORY > 0 #if LUA_OPTIMIZE_MEMORY > 0
luaL_rometatable(L, "mqtt.socket", (void *)mqtt_socket_map); // create metatable for mqtt.socket luaL_rometatable(L, "mqtt.socket", (void *)mqtt_socket_map); // create metatable for mqtt.socket
......
...@@ -200,10 +200,15 @@ static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) ...@@ -200,10 +200,15 @@ static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
return; return;
} }
if(nud->self_ref == LUA_NOREF){
NODE_DBG("self_ref null.\n");
return;
}
if(ipaddr == NULL) if(ipaddr == NULL)
{ {
NODE_ERR( "DNS Fail!\n" ); NODE_ERR( "DNS Fail!\n" );
return; goto end;
} }
// ipaddr->addr is a uint32_t ip // ipaddr->addr is a uint32_t ip
...@@ -214,16 +219,12 @@ static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) ...@@ -214,16 +219,12 @@ static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
c_sprintf(ip_str, IPSTR, IP2STR(&(ipaddr->addr))); c_sprintf(ip_str, IPSTR, IP2STR(&(ipaddr->addr)));
} }
if(nud->self_ref == LUA_NOREF){
NODE_DBG("self_ref null.\n");
return;
}
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_dns_found_ref); // the callback function lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_dns_found_ref); // the callback function
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(conn) to callback func in lua lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(conn) to callback func in lua
lua_pushstring(gL, ip_str); // the ip para lua_pushstring(gL, ip_str); // the ip para
lua_call(gL, 2, 0); lua_call(gL, 2, 0);
end:
if((pesp_conn->type == ESPCONN_TCP && pesp_conn->proto.tcp->remote_port == 0) if((pesp_conn->type == ESPCONN_TCP && pesp_conn->proto.tcp->remote_port == 0)
|| (pesp_conn->type == ESPCONN_UDP && pesp_conn->proto.udp->remote_port == 0) ){ || (pesp_conn->type == ESPCONN_UDP && pesp_conn->proto.udp->remote_port == 0) ){
lua_gc(gL, LUA_GCSTOP, 0); lua_gc(gL, LUA_GCSTOP, 0);
...@@ -597,12 +598,22 @@ static void socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) ...@@ -597,12 +598,22 @@ static void socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
NODE_DBG("pesp_conn null.\n"); NODE_DBG("pesp_conn null.\n");
return; return;
} }
lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse;
if(nud == NULL)
return;
if(gL == NULL)
return;
if(ipaddr == NULL) if(ipaddr == NULL)
{ {
dns_reconn_count++; dns_reconn_count++;
if( dns_reconn_count >= 5 ){ if( dns_reconn_count >= 5 ){
NODE_ERR( "DNS Fail!\n" ); NODE_ERR( "DNS Fail!\n" );
lua_gc(gL, LUA_GCSTOP, 0);
if(nud->self_ref != LUA_NOREF){
luaL_unref(gL, LUA_REGISTRYINDEX, nud->self_ref);
nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self
}
lua_gc(gL, LUA_GCRESTART, 0);
return; return;
} }
NODE_ERR( "DNS retry %d!\n", dns_reconn_count ); NODE_ERR( "DNS retry %d!\n", dns_reconn_count );
...@@ -1241,6 +1252,31 @@ static int net_socket_unhold( lua_State* L ) ...@@ -1241,6 +1252,31 @@ static int net_socket_unhold( lua_State* L )
return 0; return 0;
} }
// Lua: ip,port = sk:getpeer()
static int net_socket_getpeer( lua_State* L )
{
lnet_userdata *nud;
const char *mt = "net.socket";
nud = (lnet_userdata *)luaL_checkudata(L, 1, mt);
luaL_argcheck(L, nud, 1, "Server/Socket expected");
if(nud!=NULL && nud->pesp_conn!=NULL ){
char temp[20] = {0};
c_sprintf(temp, IPSTR, IP2STR( &(nud->pesp_conn->proto.tcp->remote_ip) ) );
if ( nud->pesp_conn->proto.tcp->remote_port != 0 ) {
lua_pushstring( L, temp );
lua_pushinteger( L, nud->pesp_conn->proto.tcp->remote_port );
} else {
lua_pushnil( L );
lua_pushnil( L );
}
} else {
lua_pushnil( L );
lua_pushnil( L );
}
return 2;
}
// Lua: socket:dns( string, function(ip) ) // Lua: socket:dns( string, function(ip) )
static int net_socket_dns( lua_State* L ) static int net_socket_dns( lua_State* L )
{ {
...@@ -1302,6 +1338,7 @@ static const LUA_REG_TYPE net_socket_map[] = ...@@ -1302,6 +1338,7 @@ static const LUA_REG_TYPE net_socket_map[] =
{ LSTRKEY( "hold" ), LFUNCVAL ( net_socket_hold ) }, { LSTRKEY( "hold" ), LFUNCVAL ( net_socket_hold ) },
{ LSTRKEY( "unhold" ), LFUNCVAL ( net_socket_unhold ) }, { LSTRKEY( "unhold" ), LFUNCVAL ( net_socket_unhold ) },
{ LSTRKEY( "dns" ), LFUNCVAL ( net_socket_dns ) }, { LSTRKEY( "dns" ), LFUNCVAL ( net_socket_dns ) },
{ LSTRKEY( "getpeer" ), LFUNCVAL ( net_socket_getpeer ) },
// { LSTRKEY( "delete" ), LFUNCVAL ( net_socket_delete ) }, // { LSTRKEY( "delete" ), LFUNCVAL ( net_socket_delete ) },
{ LSTRKEY( "__gc" ), LFUNCVAL ( net_socket_delete ) }, { LSTRKEY( "__gc" ), LFUNCVAL ( net_socket_delete ) },
#if LUA_OPTIMIZE_MEMORY > 0 #if LUA_OPTIMIZE_MEMORY > 0
......
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
#include "user_interface.h" #include "user_interface.h"
#include "flash_api.h" #include "flash_api.h"
#include "flash_fs.h" #include "flash_fs.h"
#include "user_version.h"
#define CPU80MHZ 80
#define CPU160MHZ 160
// Lua: restart() // Lua: restart()
static int node_restart( lua_State* L ) static int node_restart( lua_State* L )
...@@ -79,9 +83,13 @@ static int node_info( lua_State* L ) ...@@ -79,9 +83,13 @@ static int node_info( lua_State* L )
lua_pushinteger(L, NODE_VERSION_REVISION); lua_pushinteger(L, NODE_VERSION_REVISION);
lua_pushinteger(L, system_get_chip_id()); // chip id lua_pushinteger(L, system_get_chip_id()); // chip id
lua_pushinteger(L, spi_flash_get_id()); // flash id lua_pushinteger(L, spi_flash_get_id()); // flash id
lua_pushinteger(L, flash_get_size_byte() / 1024); // flash size in KB #if defined(FLASH_SAFE_API)
lua_pushinteger(L, flash_get_mode()); lua_pushinteger(L, flash_safe_get_size_byte() / 1024); // flash size in KB
lua_pushinteger(L, flash_get_speed()); #else
lua_pushinteger(L, flash_rom_get_size_byte() / 1024); // flash size in KB
#endif // defined(FLASH_SAFE_API)
lua_pushinteger(L, flash_rom_get_mode());
lua_pushinteger(L, flash_rom_get_speed());
return 8; return 8;
} }
...@@ -111,16 +119,15 @@ static int node_flashid( lua_State* L ) ...@@ -111,16 +119,15 @@ static int node_flashid( lua_State* L )
// Lua: flashsize() // Lua: flashsize()
static int node_flashsize( lua_State* L ) static int node_flashsize( lua_State* L )
{ {
//uint32_t sz = 0; if (lua_type(L, 1) == LUA_TNUMBER)
//if(lua_type(L, 1) == LUA_TNUMBER) {
//{ flash_rom_set_size_byte(luaL_checkinteger(L, 1));
// sz = luaL_checkinteger(L, 1); }
// if(sz > 0) #if defined(FLASH_SAFE_API)
// { uint32_t sz = flash_safe_get_size_byte();
// flash_set_size_byte(sz); #else
// } uint32_t sz = flash_rom_get_size_byte();
//} #endif // defined(FLASH_SAFE_API)
uint32_t sz = flash_get_size_byte();
lua_pushinteger( L, sz ); lua_pushinteger( L, sz );
return 1; return 1;
} }
...@@ -145,7 +152,7 @@ static int node_led( lua_State* L ) ...@@ -145,7 +152,7 @@ static int node_led( lua_State* L )
if ( lua_isnumber(L, 1) ) if ( lua_isnumber(L, 1) )
{ {
low = lua_tointeger(L, 1); low = lua_tointeger(L, 1);
if ( low < 0 ){ if ( low < 0 ) {
return luaL_error( L, "wrong arg type" ); return luaL_error( L, "wrong arg type" );
} }
} else { } else {
...@@ -154,7 +161,7 @@ static int node_led( lua_State* L ) ...@@ -154,7 +161,7 @@ static int node_led( lua_State* L )
if ( lua_isnumber(L, 2) ) if ( lua_isnumber(L, 2) )
{ {
high = lua_tointeger(L, 2); high = lua_tointeger(L, 2);
if ( high < 0 ){ if ( high < 0 ) {
return luaL_error( L, "wrong arg type" ); return luaL_error( L, "wrong arg type" );
} }
} else { } else {
...@@ -168,8 +175,8 @@ static int node_led( lua_State* L ) ...@@ -168,8 +175,8 @@ static int node_led( lua_State* L )
static int long_key_ref = LUA_NOREF; static int long_key_ref = LUA_NOREF;
static int short_key_ref = LUA_NOREF; static int short_key_ref = LUA_NOREF;
void default_long_press(void *arg){ void default_long_press(void *arg) {
if(led_high_count == 12 && led_low_count == 12){ if (led_high_count == 12 && led_low_count == 12) {
led_low_count = led_high_count = 6; led_low_count = led_high_count = 6;
} else { } else {
led_low_count = led_high_count = 12; led_low_count = led_high_count = 12;
...@@ -179,29 +186,29 @@ void default_long_press(void *arg){ ...@@ -179,29 +186,29 @@ void default_long_press(void *arg){
// NODE_DBG("default_long_press is called. hc: %d, lc: %d\n", led_high_count, led_low_count); // NODE_DBG("default_long_press is called. hc: %d, lc: %d\n", led_high_count, led_low_count);
} }
void default_short_press(void *arg){ void default_short_press(void *arg) {
system_restart(); system_restart();
} }
void key_long_press(void *arg){ void key_long_press(void *arg) {
NODE_DBG("key_long_press is called.\n"); NODE_DBG("key_long_press is called.\n");
if(long_key_ref == LUA_NOREF){ if (long_key_ref == LUA_NOREF) {
default_long_press(arg); default_long_press(arg);
return; return;
} }
if(!gL) if (!gL)
return; return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, long_key_ref); lua_rawgeti(gL, LUA_REGISTRYINDEX, long_key_ref);
lua_call(gL, 0, 0); lua_call(gL, 0, 0);
} }
void key_short_press(void *arg){ void key_short_press(void *arg) {
NODE_DBG("key_short_press is called.\n"); NODE_DBG("key_short_press is called.\n");
if(short_key_ref == LUA_NOREF){ if (short_key_ref == LUA_NOREF) {
default_short_press(arg); default_short_press(arg);
return; return;
} }
if(!gL) if (!gL)
return; return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, short_key_ref); lua_rawgeti(gL, LUA_REGISTRYINDEX, short_key_ref);
lua_call(gL, 0, 0); lua_call(gL, 0, 0);
...@@ -217,22 +224,22 @@ static int node_key( lua_State* L ) ...@@ -217,22 +224,22 @@ static int node_key( lua_State* L )
if (str == NULL) if (str == NULL)
return luaL_error( L, "wrong arg type" ); return luaL_error( L, "wrong arg type" );
if(sl == 5 && c_strcmp(str, "short") == 0){ if (sl == 5 && c_strcmp(str, "short") == 0) {
ref = &short_key_ref; ref = &short_key_ref;
}else if(sl == 4 && c_strcmp(str, "long") == 0){ } else if (sl == 4 && c_strcmp(str, "long") == 0) {
ref = &long_key_ref; ref = &long_key_ref;
}else{ } else {
ref = &short_key_ref; ref = &short_key_ref;
} }
gL = L; gL = L;
// luaL_checkanyfunction(L, 2); // luaL_checkanyfunction(L, 2);
if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION){ 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 lua_pushvalue(L, 2); // copy argument (func) to the top of stack
if(*ref != LUA_NOREF) if (*ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, *ref); luaL_unref(L, LUA_REGISTRYINDEX, *ref);
*ref = luaL_ref(L, LUA_REGISTRYINDEX); *ref = luaL_ref(L, LUA_REGISTRYINDEX);
} else { // unref the key press function } else { // unref the key press function
if(*ref != LUA_NOREF) if (*ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, *ref); luaL_unref(L, LUA_REGISTRYINDEX, *ref);
*ref = LUA_NOREF; *ref = LUA_NOREF;
} }
...@@ -247,15 +254,15 @@ extern void dojob(lua_Load *load); ...@@ -247,15 +254,15 @@ extern void dojob(lua_Load *load);
// Lua: input("string") // Lua: input("string")
static int node_input( lua_State* L ) static int node_input( lua_State* L )
{ {
size_t l=0; size_t l = 0;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
if (s != NULL && l > 0 && l < LUA_MAXINPUT - 1) if (s != NULL && l > 0 && l < LUA_MAXINPUT - 1)
{ {
lua_Load *load = &gLoad; lua_Load *load = &gLoad;
if(load->line_position == 0){ if (load->line_position == 0) {
c_memcpy(load->line, s, l); c_memcpy(load->line, s, l);
load->line[l+1] = '\0'; load->line[l + 1] = '\0';
load->line_position = c_strlen(load->line)+1; load->line_position = c_strlen(load->line) + 1;
load->done = 1; load->done = 1;
NODE_DBG("Get command:\n"); NODE_DBG("Get command:\n");
NODE_DBG(load->line); // buggy here NODE_DBG(load->line); // buggy here
...@@ -270,18 +277,18 @@ static int node_input( lua_State* L ) ...@@ -270,18 +277,18 @@ static int node_input( lua_State* L )
static int output_redir_ref = LUA_NOREF; static int output_redir_ref = LUA_NOREF;
static int serial_debug = 1; static int serial_debug = 1;
void output_redirect(const char *str){ void output_redirect(const char *str) {
// if(c_strlen(str)>=TX_BUFF_SIZE){ // if(c_strlen(str)>=TX_BUFF_SIZE){
// NODE_ERR("output too long.\n"); // NODE_ERR("output too long.\n");
// return; // return;
// } // }
if(output_redir_ref == LUA_NOREF || !gL){ if (output_redir_ref == LUA_NOREF || !gL) {
uart0_sendStr(str); uart0_sendStr(str);
return; return;
} }
if(serial_debug!=0){ if (serial_debug != 0) {
uart0_sendStr(str); uart0_sendStr(str);
} }
...@@ -295,13 +302,13 @@ static int node_output( lua_State* L ) ...@@ -295,13 +302,13 @@ static int node_output( lua_State* L )
{ {
gL = L; gL = L;
// luaL_checkanyfunction(L, 1); // luaL_checkanyfunction(L, 1);
if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION){ if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION) {
lua_pushvalue(L, 1); // copy argument (func) to the top of stack lua_pushvalue(L, 1); // copy argument (func) to the top of stack
if(output_redir_ref != LUA_NOREF) if (output_redir_ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref); luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref);
output_redir_ref = luaL_ref(L, LUA_REGISTRYINDEX); output_redir_ref = luaL_ref(L, LUA_REGISTRYINDEX);
} else { // unref the key press function } else { // unref the key press function
if(output_redir_ref != LUA_NOREF) if (output_redir_ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref); luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref);
output_redir_ref = LUA_NOREF; output_redir_ref = LUA_NOREF;
serial_debug = 1; serial_debug = 1;
...@@ -311,7 +318,7 @@ static int node_output( lua_State* L ) ...@@ -311,7 +318,7 @@ static int node_output( lua_State* L )
if ( lua_isnumber(L, 2) ) if ( lua_isnumber(L, 2) )
{ {
serial_debug = lua_tointeger(L, 2); serial_debug = lua_tointeger(L, 2);
if(serial_debug!=0) if (serial_debug != 0)
serial_debug = 1; serial_debug = 1;
} else { } else {
serial_debug = 1; // default to 1 serial_debug = 1; // default to 1
...@@ -324,13 +331,13 @@ static int writer(lua_State* L, const void* p, size_t size, void* u) ...@@ -324,13 +331,13 @@ 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 ((FS_OPEN_OK - 1) == 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 != fs_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;
} }
...@@ -342,51 +349,69 @@ static int node_compile( lua_State* L ) ...@@ -342,51 +349,69 @@ static int node_compile( lua_State* L )
int file_fd = FS_OPEN_OK - 1; int file_fd = FS_OPEN_OK - 1;
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 ) if ( len > FS_NAME_MAX_LENGTH )
return luaL_error(L, "filename too long"); return luaL_error(L, "filename too long");
char output[FS_NAME_MAX_LENGTH]; char output[FS_NAME_MAX_LENGTH];
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) )
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) {
return luaL_error(L, lua_tostring(L,-1)); return luaL_error(L, lua_tostring(L, -1));
} }
f = toproto(L,-1); f = toproto(L, -1);
int stripping = 1; /* strip debug information? */ int stripping = 1; /* strip debug information? */
file_fd = fs_open(output, fs_mode2flag("w+")); file_fd = fs_open(output, fs_mode2flag("w+"));
if(file_fd < FS_OPEN_OK) if (file_fd < FS_OPEN_OK)
{ {
return luaL_error(L, "cannot open/write to file"); return luaL_error(L, "cannot open/write to file");
} }
lua_lock(L); lua_lock(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);
fs_flush(file_fd); fs_flush(file_fd);
fs_close(file_fd); fs_close(file_fd);
file_fd = FS_OPEN_OK - 1; file_fd = FS_OPEN_OK - 1;
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");
} }
if (result==LUA_ERR_CC_NOTINTEGER){ if (result == LUA_ERR_CC_NOTINTEGER) {
return luaL_error(L, "target lua_Number is integral but fractional value found"); return luaL_error(L, "target lua_Number is integral but fractional value found");
} }
return 0; return 0;
} }
// Lua: setcpufreq(mhz)
// mhz is either CPU80MHZ od CPU160MHZ
static int node_setcpufreq(lua_State* L)
{
// http://www.esp8266.com/viewtopic.php?f=21&t=1369
uint32_t new_freq = luaL_checkinteger(L, 1);
if (new_freq == CPU160MHZ){
REG_SET_BIT(0x3ff00014, BIT(0));
os_update_cpu_frequency(CPU160MHZ);
} else {
REG_CLR_BIT(0x3ff00014, BIT(0));
os_update_cpu_frequency(CPU80MHZ);
}
new_freq = ets_get_cpu_frequency();
lua_pushinteger(L, new_freq);
return 1;
}
// Module function map // Module function map
#define MIN_OPT_LEVEL 2 #define MIN_OPT_LEVEL 2
#include "lrodefs.h" #include "lrodefs.h"
...@@ -407,6 +432,9 @@ const LUA_REG_TYPE node_map[] = ...@@ -407,6 +432,9 @@ const LUA_REG_TYPE node_map[] =
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) }, { LSTRKEY( "output" ), LFUNCVAL( node_output ) },
{ LSTRKEY( "readvdd33" ), LFUNCVAL( node_readvdd33) }, { LSTRKEY( "readvdd33" ), LFUNCVAL( node_readvdd33) },
{ LSTRKEY( "compile" ), LFUNCVAL( node_compile) }, { LSTRKEY( "compile" ), LFUNCVAL( node_compile) },
{ LSTRKEY( "CPU80MHZ" ), LNUMVAL( CPU80MHZ ) },
{ LSTRKEY( "CPU160MHZ" ), LNUMVAL( CPU160MHZ ) },
{ LSTRKEY( "setcpufreq" ), LFUNCVAL( node_setcpufreq) },
// Combined to dsleep(us, option) // Combined to dsleep(us, option)
// { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) }, // { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) },
#if LUA_OPTIMIZE_MEMORY > 0 #if LUA_OPTIMIZE_MEMORY > 0
......
...@@ -148,24 +148,30 @@ static int tmr_wdclr( lua_State* L ) ...@@ -148,24 +148,30 @@ static int tmr_wdclr( lua_State* L )
} }
static os_timer_t rtc_timer_updator; static os_timer_t rtc_timer_updator;
static uint64_t cur_count = 0; static uint32_t cur_count = 0;
static uint64_t rtc_us = 0; static uint32_t rtc_10ms = 0;
void rtc_timer_update_cb(void *arg){ void rtc_timer_update_cb(void *arg){
uint64_t t = (uint64_t)system_get_rtc_time(); uint32_t t = (uint32_t)system_get_rtc_time();
uint64_t delta = (t>=cur_count)?(t - cur_count):(0x100000000 + t - cur_count); uint32_t delta = 0;
if(t>=cur_count){
delta = t-cur_count;
}else{
delta = 0xFFFFFFF - cur_count + t + 1;
}
// uint64_t delta = (t>=cur_count)?(t - cur_count):(0x100000000 + t - cur_count);
// NODE_ERR("%x\n",t); // NODE_ERR("%x\n",t);
cur_count = t; cur_count = t;
unsigned c = system_rtc_clock_cali_proc(); uint32_t c = system_rtc_clock_cali_proc();
uint64_t itg = c >> 12; uint32_t itg = c >> 12; // ~=5
uint64_t dec = c & 0xFFF; uint32_t dec = c & 0xFFF; // ~=2ff
rtc_us += (delta*itg + ((delta*dec)>>12)); rtc_10ms += (delta*itg + ((delta*dec)>>12)) / 10000;
// TODO: store rtc_us to rtc memory. // TODO: store rtc_10ms to rtc memory.
} }
// Lua: time() , return rtc time in second // Lua: time() , return rtc time in second
static int tmr_time( lua_State* L ) static int tmr_time( lua_State* L )
{ {
uint64_t local = rtc_us; uint32_t local = rtc_10ms;
lua_pushinteger( L, ((uint32_t)(local/1000000)) & 0x7FFFFFFF ); lua_pushinteger( L, ((uint32_t)(local/100)) & 0x7FFFFFFF );
return 1; return 1;
} }
......
This diff is collapsed.
...@@ -8,47 +8,56 @@ ...@@ -8,47 +8,56 @@
* from user Markus Gritsch. * from user Markus Gritsch.
* I just put this code into its own module and pushed into a forked repo, * I just put this code into its own module and pushed into a forked repo,
* to easily create a pull request. Thanks to Markus Gritsch for the code. * to easily create a pull request. Thanks to Markus Gritsch for the code.
*
*/ */
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// -- This WS2812 code must be compiled with -O2 to get the timing right. // -- This WS2812 code must be compiled with -O2 to get the timing right. Read this:
// -- http://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/ // -- http://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
// The ICACHE_FLASH_ATTR is there to trick the compiler and get the very first pulse width correct. // -- The ICACHE_FLASH_ATTR is there to trick the compiler and get the very first pulse width correct.
static void ICACHE_FLASH_ATTR send_ws_0(uint8_t gpio) { static void ICACHE_FLASH_ATTR send_ws_0(uint8_t gpio) {
uint8_t i; uint8_t i;
i = 4; i = 4; while (i--) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << gpio);
while (i--) i = 9; while (i--) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << gpio);
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << gpio);
i = 9;
while (i--)
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << gpio);
} }
static void ICACHE_FLASH_ATTR send_ws_1(uint8_t gpio) { static void ICACHE_FLASH_ATTR send_ws_1(uint8_t gpio) {
uint8_t i; uint8_t i;
i = 8; i = 8; while (i--) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << gpio);
while (i--) i = 6; while (i--) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << gpio);
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << gpio);
i = 6;
while (i--)
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << gpio);
} }
// Lua: ws2812.write(pin, "string") // Lua: ws2812.write(pin, "string")
// Byte triples in the string are interpreted as G R B values. // Byte triples in the string are interpreted as R G B values and sent to the hardware as G R B.
// ws2812.write(4, string.char(0, 255, 0)) uses GPIO2 and sets the first LED red. // ws2812.write(4, string.char(255, 0, 0)) uses GPIO2 and sets the first LED red.
// ws2812.write(3, string.char(0, 0, 255):rep(10)) uses GPIO0 and sets ten LEDs blue. // ws2812.write(3, string.char(0, 0, 255):rep(10)) uses GPIO0 and sets ten LEDs blue.
// ws2812.write(4, string.char(255, 0, 0, 255, 255, 255)) first LED green, second LED white. // ws2812.write(4, string.char(0, 255, 0, 255, 255, 255)) first LED green, second LED white.
static int ICACHE_FLASH_ATTR ws2812_write(lua_State* L) { static int ICACHE_FLASH_ATTR ws2812_writergb(lua_State* L)
{
const uint8_t pin = luaL_checkinteger(L, 1); const uint8_t pin = luaL_checkinteger(L, 1);
size_t length; size_t length;
const char *buffer = luaL_checklstring(L, 2, &length); char *buffer = (char *)luaL_checklstring(L, 2, &length); // Cast away the constness.
// Initialize the output pin:
platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT); platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT);
platform_gpio_write(pin, 0); platform_gpio_write(pin, 0);
os_delay_us(10);
// Ignore incomplete Byte triples at the end of buffer:
length -= length % 3;
// Rearrange R G B values to G R B order needed by WS2812 LEDs:
size_t i;
for (i = 0; i < length; i += 3) {
const char r = buffer[i];
const char g = buffer[i + 1];
buffer[i] = g;
buffer[i + 1] = r;
}
// Do not remove these:
os_delay_us(1);
os_delay_us(1);
// Send the buffer:
os_intr_lock(); os_intr_lock();
const char * const end = buffer + length; const char * const end = buffer + length;
while (buffer != end) { while (buffer != end) {
...@@ -68,7 +77,7 @@ static int ICACHE_FLASH_ATTR ws2812_write(lua_State* L) { ...@@ -68,7 +77,7 @@ static int ICACHE_FLASH_ATTR ws2812_write(lua_State* L) {
#include "lrodefs.h" #include "lrodefs.h"
const LUA_REG_TYPE ws2812_map[] = const LUA_REG_TYPE ws2812_map[] =
{ {
{ LSTRKEY( "write" ), LFUNCVAL( ws2812_write )}, { LSTRKEY( "writergb" ), LFUNCVAL( ws2812_writergb )},
{ LNILKEY, LNILVAL} { LNILKEY, LNILVAL}
}; };
...@@ -77,6 +86,3 @@ LUALIB_API int luaopen_ws2812(lua_State *L) { ...@@ -77,6 +86,3 @@ LUALIB_API int luaopen_ws2812(lua_State *L) {
LREGISTER(L, "ws2812", ws2812_map); LREGISTER(L, "ws2812", ws2812_map);
return 1; return 1;
} }
// ----------------------------------------------------------------------------
...@@ -30,7 +30,11 @@ ...@@ -30,7 +30,11 @@
#elif defined(FLASH_16M) #elif defined(FLASH_16M)
#define FLASH_SEC_NUM 0x1000 #define FLASH_SEC_NUM 0x1000
#elif defined(FLASH_AUTOSIZE) #elif defined(FLASH_AUTOSIZE)
#define FLASH_SEC_NUM (flash_get_sec_num()) #if defined(FLASH_SAFE_API)
#define FLASH_SEC_NUM (flash_safe_get_sec_num())
#else
#define FLASH_SEC_NUM (flash_rom_get_sec_num())
#endif // defined(FLASH_SAFE_API)
#else #else
#define FLASH_SEC_NUM 0x80 #define FLASH_SEC_NUM 0x80
#endif #endif
...@@ -54,8 +58,14 @@ ...@@ -54,8 +58,14 @@
// SpiFlashOpResult spi_flash_erase_sector(uint16 sec); // SpiFlashOpResult spi_flash_erase_sector(uint16 sec);
// SpiFlashOpResult spi_flash_write(uint32 des_addr, uint32 *src_addr, uint32 size); // SpiFlashOpResult spi_flash_write(uint32 des_addr, uint32 *src_addr, uint32 size);
// SpiFlashOpResult spi_flash_read(uint32 src_addr, uint32 *des_addr, uint32 size); // SpiFlashOpResult spi_flash_read(uint32 src_addr, uint32 *des_addr, uint32 size);
#if defined(FLASH_SAFE_API)
#define flash_write flash_safe_write
#define flash_erase flash_safe_erase_sector
#define flash_read flash_safe_read
#else
#define flash_write spi_flash_write #define flash_write spi_flash_write
#define flash_erase spi_flash_erase_sector #define flash_erase spi_flash_erase_sector
#define flash_read spi_flash_read #define flash_read spi_flash_read
#endif // defined(FLASH_SAFE_API)
#endif // #ifndef __CPU_ESP8266_H__ #endif // #ifndef __CPU_ESP8266_H__
...@@ -20,22 +20,92 @@ static volatile const uint8_t flash_init_data[128] ICACHE_STORE_ATTR ICACHE_RODA ...@@ -20,22 +20,92 @@ static volatile const uint8_t flash_init_data[128] ICACHE_STORE_ATTR ICACHE_RODA
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
SPIFlashInfo flash_get_info(void) uint32_t flash_detect_size_byte(void)
{
#define FLASH_BUFFER_SIZE_DETECT 32
uint32_t dummy_size = FLASH_SIZE_256KBYTE;
uint8_t data_orig[FLASH_BUFFER_SIZE_DETECT] ICACHE_STORE_ATTR = {0};
uint8_t data_new[FLASH_BUFFER_SIZE_DETECT] ICACHE_STORE_ATTR = {0};
if (SPI_FLASH_RESULT_OK == flash_safe_read(0, (uint32 *)data_orig, FLASH_BUFFER_SIZE_DETECT))
{
dummy_size = FLASH_SIZE_256KBYTE;
while ((dummy_size < FLASH_SIZE_16MBYTE) &&
(SPI_FLASH_RESULT_OK == flash_safe_read(dummy_size, (uint32 *)data_new, FLASH_BUFFER_SIZE_DETECT)) &&
(0 != os_memcmp(data_orig, data_new, FLASH_BUFFER_SIZE_DETECT))
)
{
dummy_size *= 2;
}
};
return dummy_size;
#undef FLASH_BUFFER_SIZE_DETECT
}
uint32_t flash_safe_get_size_byte(void)
{
static uint32_t flash_size = 0;
if (flash_size == 0)
{
flash_size = flash_detect_size_byte();
}
return flash_size;
}
uint16_t flash_safe_get_sec_num(void)
{
return (flash_safe_get_size_byte() / (SPI_FLASH_SEC_SIZE));
}
SpiFlashOpResult flash_safe_read(uint32 src_addr, uint32 *des_addr, uint32 size)
{
SpiFlashOpResult result = SPI_FLASH_RESULT_ERR;
FLASH_SAFEMODE_ENTER();
result = spi_flash_read(src_addr, (uint32 *) des_addr, size);
FLASH_SAFEMODE_LEAVE();
return result;
}
SpiFlashOpResult flash_safe_write(uint32 des_addr, uint32 *src_addr, uint32 size)
{
SpiFlashOpResult result = SPI_FLASH_RESULT_ERR;
FLASH_SAFEMODE_ENTER();
result = spi_flash_write(des_addr, src_addr, size);
FLASH_SAFEMODE_LEAVE();
return result;
}
SpiFlashOpResult flash_safe_erase_sector(uint16 sec)
{
SpiFlashOpResult result = SPI_FLASH_RESULT_ERR;
FLASH_SAFEMODE_ENTER();
result = spi_flash_erase_sector(sec);
FLASH_SAFEMODE_LEAVE();
return result;
}
SPIFlashInfo flash_rom_getinfo(void)
{ {
volatile SPIFlashInfo spi_flash_info ICACHE_STORE_ATTR; volatile SPIFlashInfo spi_flash_info ICACHE_STORE_ATTR;
spi_flash_info = *((SPIFlashInfo *)(FLASH_MAP_START_ADDRESS)); // Don't use it before cache read disabled
// FLASH_DISABLE_CACHE();
// spi_flash_info = *((SPIFlashInfo *)(FLASH_ADDRESS_START_MAP));
// FLASH_ENABLE_CACHE();
// Needn't safe mode.
spi_flash_read(0, (uint32 *)(& spi_flash_info), sizeof(spi_flash_info));
return spi_flash_info; return spi_flash_info;
} }
uint8_t flash_get_size(void) uint8_t flash_rom_get_size_type(void)
{ {
return flash_get_info().size; return flash_rom_getinfo().size;
} }
uint32_t flash_get_size_byte(void) uint32_t flash_rom_get_size_byte(void)
{ {
uint32_t flash_size = 0; static uint32_t flash_size = 0;
switch (flash_get_info().size) if (flash_size == 0)
{
switch (flash_rom_getinfo().size)
{ {
case SIZE_2MBIT: case SIZE_2MBIT:
// 2Mbit, 256kByte // 2Mbit, 256kByte
...@@ -56,9 +126,11 @@ uint32_t flash_get_size_byte(void) ...@@ -56,9 +126,11 @@ uint32_t flash_get_size_byte(void)
case SIZE_32MBIT: case SIZE_32MBIT:
// 32Mbit, 4MByte // 32Mbit, 4MByte
flash_size = 4 * 1024 * 1024; flash_size = 4 * 1024 * 1024;
break;
case SIZE_64MBIT: case SIZE_64MBIT:
// 64Mbit, 8MByte // 64Mbit, 8MByte
flash_size = 8 * 1024 * 1024; flash_size = 8 * 1024 * 1024;
break;
case SIZE_128MBIT: case SIZE_128MBIT:
// 128Mbit, 16MByte // 128Mbit, 16MByte
flash_size = 16 * 1024 * 1024; flash_size = 16 * 1024 * 1024;
...@@ -68,26 +140,34 @@ uint32_t flash_get_size_byte(void) ...@@ -68,26 +140,34 @@ uint32_t flash_get_size_byte(void)
flash_size = 512 * 1024; flash_size = 512 * 1024;
break; break;
} }
}
return flash_size; return flash_size;
} }
bool flash_set_size(uint8_t size) bool flash_rom_set_size_type(uint8_t size)
{ {
// Dangerous, here are dinosaur infested!!!!! // Dangerous, here are dinosaur infested!!!!!
// Reboot required!!! // Reboot required!!!
// If you don't know what you're doing, your nodemcu may turn into stone ... // If you don't know what you're doing, your nodemcu may turn into stone ...
NODE_DBG("\nBEGIN SET FLASH HEADER\n");
uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR; uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR;
spi_flash_read(0, (uint32 *)data, sizeof(data)); if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
SPIFlashInfo *p_spi_flash_info = (SPIFlashInfo *)(data); {
p_spi_flash_info->size = size; ((SPIFlashInfo *)(&data[0]))->size = size;
spi_flash_erase_sector(0); if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE))
spi_flash_write(0, (uint32 *)data, sizeof(data)); {
//p_spi_flash_info = flash_get_info(); NODE_DBG("\nERASE SUCCESS\n");
//p_spi_flash_info->size = size; }
if (SPI_FLASH_RESULT_OK == spi_flash_write(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
{
NODE_DBG("\nWRITE SUCCESS, %u\n", size);
}
}
NODE_DBG("\nEND SET FLASH HEADER\n");
return true; return true;
} }
bool flash_set_size_byte(uint32_t size) bool flash_rom_set_size_byte(uint32_t size)
{ {
// Dangerous, here are dinosaur infested!!!!! // Dangerous, here are dinosaur infested!!!!!
// Reboot required!!! // Reboot required!!!
...@@ -99,27 +179,37 @@ bool flash_set_size_byte(uint32_t size) ...@@ -99,27 +179,37 @@ bool flash_set_size_byte(uint32_t size)
case 256 * 1024: case 256 * 1024:
// 2Mbit, 256kByte // 2Mbit, 256kByte
flash_size = SIZE_2MBIT; flash_size = SIZE_2MBIT;
flash_set_size(flash_size); flash_rom_set_size_type(flash_size);
break; break;
case 512 * 1024: case 512 * 1024:
// 4Mbit, 512kByte // 4Mbit, 512kByte
flash_size = SIZE_4MBIT; flash_size = SIZE_4MBIT;
flash_set_size(flash_size); flash_rom_set_size_type(flash_size);
break; break;
case 1 * 1024 * 1024: case 1 * 1024 * 1024:
// 8Mbit, 1MByte // 8Mbit, 1MByte
flash_size = SIZE_8MBIT; flash_size = SIZE_8MBIT;
flash_set_size(flash_size); flash_rom_set_size_type(flash_size);
break; break;
case 2 * 1024 * 1024: case 2 * 1024 * 1024:
// 16Mbit, 2MByte // 16Mbit, 2MByte
flash_size = SIZE_16MBIT; flash_size = SIZE_16MBIT;
flash_set_size(flash_size); flash_rom_set_size_type(flash_size);
break; break;
case 4 * 1024 * 1024: case 4 * 1024 * 1024:
// 32Mbit, 4MByte // 32Mbit, 4MByte
flash_size = SIZE_32MBIT; flash_size = SIZE_32MBIT;
flash_set_size(flash_size); flash_rom_set_size_type(flash_size);
break;
case 8 * 1024 * 1024:
// 64Mbit, 8MByte
flash_size = SIZE_64MBIT;
flash_rom_set_size_type(flash_size);
break;
case 16 * 1024 * 1024:
// 128Mbit, 16MByte
flash_size = SIZE_128MBIT;
flash_rom_set_size_type(flash_size);
break; break;
default: default:
// Unknown flash size. // Unknown flash size.
...@@ -129,14 +219,22 @@ bool flash_set_size_byte(uint32_t size) ...@@ -129,14 +219,22 @@ bool flash_set_size_byte(uint32_t size)
return result; return result;
} }
uint16_t flash_get_sec_num(void) uint16_t flash_rom_get_sec_num(void)
{ {
return flash_get_size_byte() / SPI_FLASH_SEC_SIZE; //static uint16_t sec_num = 0;
// return flash_rom_get_size_byte() / (SPI_FLASH_SEC_SIZE);
// c_printf("\nflash_rom_get_size_byte()=%d\n", ( flash_rom_get_size_byte() / (SPI_FLASH_SEC_SIZE) ));
// if( sec_num == 0 )
//{
// sec_num = 4 * 1024 * 1024 / (SPI_FLASH_SEC_SIZE);
//}
//return sec_num;
return ( flash_rom_get_size_byte() / (SPI_FLASH_SEC_SIZE) );
} }
uint8_t flash_get_mode(void) uint8_t flash_rom_get_mode(void)
{ {
SPIFlashInfo spi_flash_info = flash_get_info(); SPIFlashInfo spi_flash_info = flash_rom_getinfo();
switch (spi_flash_info.mode) switch (spi_flash_info.mode)
{ {
// Reserved for future use // Reserved for future use
...@@ -152,10 +250,10 @@ uint8_t flash_get_mode(void) ...@@ -152,10 +250,10 @@ uint8_t flash_get_mode(void)
return spi_flash_info.mode; return spi_flash_info.mode;
} }
uint32_t flash_get_speed(void) uint32_t flash_rom_get_speed(void)
{ {
uint32_t speed = 0; uint32_t speed = 0;
SPIFlashInfo spi_flash_info = flash_get_info(); SPIFlashInfo spi_flash_info = flash_rom_getinfo();
switch (spi_flash_info.speed) switch (spi_flash_info.speed)
{ {
case SPEED_40MHZ: case SPEED_40MHZ:
...@@ -178,11 +276,55 @@ uint32_t flash_get_speed(void) ...@@ -178,11 +276,55 @@ uint32_t flash_get_speed(void)
return speed; return speed;
} }
bool flash_rom_set_speed(uint32_t speed)
{
// Dangerous, here are dinosaur infested!!!!!
// Reboot required!!!
// If you don't know what you're doing, your nodemcu may turn into stone ...
NODE_DBG("\nBEGIN SET FLASH HEADER\n");
uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR;
uint8_t speed_type = SPEED_40MHZ;
if (speed < 26700000)
{
speed_type = SPEED_20MHZ;
}
else if (speed < 40000000)
{
speed_type = SPEED_26MHZ;
}
else if (speed < 80000000)
{
speed_type = SPEED_40MHZ;
}
else if (speed >= 80000000)
{
speed_type = SPEED_80MHZ;
}
if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
{
((SPIFlashInfo *)(&data[0]))->speed = speed_type;
if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE))
{
NODE_DBG("\nERASE SUCCESS\n");
}
if (SPI_FLASH_RESULT_OK == spi_flash_write(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
{
NODE_DBG("\nWRITE SUCCESS, %u\n", speed_type);
}
}
NODE_DBG("\nEND SET FLASH HEADER\n");
return true;
}
bool flash_init_data_written(void) bool flash_init_data_written(void)
{ {
// FLASH SEC - 4 // FLASH SEC - 4
uint32_t data[2] ICACHE_STORE_ATTR; uint32_t data[2] ICACHE_STORE_ATTR;
if (SPI_FLASH_RESULT_OK == spi_flash_read((flash_get_sec_num() - 4) * SPI_FLASH_SEC_SIZE, (uint32 *)data, sizeof(data))) #if defined(FLASH_SAFE_API)
if (SPI_FLASH_RESULT_OK == flash_safe_read((flash_rom_get_sec_num() - 4) * SPI_FLASH_SEC_SIZE, (uint32 *)data, sizeof(data)))
#else
if (SPI_FLASH_RESULT_OK == spi_flash_read((flash_rom_get_sec_num() - 4) * SPI_FLASH_SEC_SIZE, (uint32 *)data, sizeof(data)))
#endif // defined(FLASH_SAFE_API)
{ {
if (data[0] == 0xFFFFFFFF && data[1] == 0xFFFFFFFF) if (data[0] == 0xFFFFFFFF && data[1] == 0xFFFFFFFF)
{ {
...@@ -199,13 +341,23 @@ bool flash_init_data_default(void) ...@@ -199,13 +341,23 @@ bool flash_init_data_default(void)
// Reboot required!!! // Reboot required!!!
// It will init system data to default! // It will init system data to default!
bool result = false; bool result = false;
if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_get_sec_num() - 4))) #if defined(FLASH_SAFE_API)
if (SPI_FLASH_RESULT_OK == flash_safe_erase_sector((flash_safe_get_sec_num() - 4)))
{ {
if (SPI_FLASH_RESULT_OK == spi_flash_write((flash_get_sec_num() - 4) * SPI_FLASH_SEC_SIZE, (uint32 *)flash_init_data, 128)) if (SPI_FLASH_RESULT_OK == flash_safe_write((flash_safe_get_sec_num() - 4) * SPI_FLASH_SEC_SIZE, (uint32 *)flash_init_data, 128))
{ {
result = true; result = true;
} }
} }
#else
if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_rom_get_sec_num() - 4)))
{
if (SPI_FLASH_RESULT_OK == spi_flash_write((flash_rom_get_sec_num() - 4) * SPI_FLASH_SEC_SIZE, (uint32 *)flash_init_data, 128))
{
result = true;
}
}
#endif // defined(FLASH_SAFE_API)
return result; return result;
} }
...@@ -216,8 +368,13 @@ bool flash_init_data_blank(void) ...@@ -216,8 +368,13 @@ bool flash_init_data_blank(void)
// Reboot required!!! // Reboot required!!!
// It will init system config to blank! // It will init system config to blank!
bool result = false; bool result = false;
if ((SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_get_sec_num() - 2))) && #if defined(FLASH_SAFE_API)
(SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_get_sec_num() - 1)))) if ((SPI_FLASH_RESULT_OK == flash_safe_erase_sector((flash_rom_get_sec_num() - 2))) &&
(SPI_FLASH_RESULT_OK == flash_safe_erase_sector((flash_rom_get_sec_num() - 1))))
#else
if ((SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_rom_get_sec_num() - 2))) &&
(SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_rom_get_sec_num() - 1))))
#endif // defined(FLASH_SAFE_API)
{ {
result = true; result = true;
} }
...@@ -232,13 +389,39 @@ bool flash_self_destruct(void) ...@@ -232,13 +389,39 @@ bool flash_self_destruct(void)
return true; return true;
} }
uint8_t byte_of_aligned_array(const uint8_t* aligned_array, uint32_t index) uint8_t byte_of_aligned_array(const uint8_t *aligned_array, uint32_t index)
{ {
if( (((uint32_t)aligned_array)%4) != 0 ){ if ( (((uint32_t)aligned_array) % 4) != 0 )
{
NODE_DBG("aligned_array is not 4-byte aligned.\n"); NODE_DBG("aligned_array is not 4-byte aligned.\n");
return 0; return 0;
} }
uint32_t v = ((uint32_t *)aligned_array)[ index/4 ]; uint32_t v = ((uint32_t *)aligned_array)[ index / 4 ];
uint8_t *p = (uint8_t *) (&v); uint8_t *p = (uint8_t *) (&v);
return p[ (index%4) ]; return p[ (index % 4) ];
} }
// uint8_t flash_rom_get_checksum(void)
// {
// // SPIFlashInfo spi_flash_info ICACHE_STORE_ATTR = flash_rom_getinfo();
// // uint32_t address = sizeof(spi_flash_info) + spi_flash_info.segment_size;
// // uint32_t address_aligned_4bytes = (address + 3) & 0xFFFFFFFC;
// // uint8_t buffer[64] = {0};
// // spi_flash_read(address, (uint32 *) buffer, 64);
// // uint8_t i = 0;
// // c_printf("\nBEGIN DUMP\n");
// // for (i = 0; i < 64; i++)
// // {
// // c_printf("%02x," , buffer[i]);
// // }
// // i = (address + 0x10) & 0x10 - 1;
// // c_printf("\nSIZE:%d CHECK SUM:%02x\n", spi_flash_info.segment_size, buffer[i]);
// // c_printf("\nEND DUMP\n");
// // return buffer[0];
// return 0;
// }
// uint8_t flash_rom_calc_checksum(void)
// {
// return 0;
// }
\ No newline at end of file
...@@ -3,34 +3,62 @@ ...@@ -3,34 +3,62 @@
#include "ets_sys.h" #include "ets_sys.h"
#include "user_config.h" #include "user_config.h"
#include "cpu_esp8266.h" #include "cpu_esp8266.h"
#define FLASH_MAP_START_ADDRESS (INTERNAL_FLASH_START_ADDRESS)
#define FLASH_ADDRESS_START_MAP (INTERNAL_FLASH_START_ADDRESS)
#define FLASH_SIZE_2MBIT (2 * 1024 * 1024)
#define FLASH_SIZE_4MBIT (4 * 1024 * 1024)
#define FLASH_SIZE_8MBIT (8 * 1024 * 1024)
#define FLASH_SIZE_16MBIT (16 * 1024 * 1024)
#define FLASH_SIZE_32MBIT (32 * 1024 * 1024)
#define FLASH_SIZE_64MBIT (64 * 1024 * 1024)
#define FLASH_SIZE_128MBIT (128 * 1024 * 1024)
#define FLASH_SIZE_256KBYTE (FLASH_SIZE_2MBIT / 8)
#define FLASH_SIZE_512KBYTE (FLASH_SIZE_4MBIT / 8)
#define FLASH_SIZE_1MBYTE (FLASH_SIZE_8MBIT / 8)
#define FLASH_SIZE_2MBYTE (FLASH_SIZE_16MBIT / 8)
#define FLASH_SIZE_4MBYTE (FLASH_SIZE_32MBIT / 8)
#define FLASH_SIZE_8MBYTE (FLASH_SIZE_64MBIT / 8)
#define FLASH_SIZE_16MBYTE (FLASH_SIZE_128MBIT/ 8)
#define FLASH_SAFEMODE_ENTER() \
do { \
extern SpiFlashChip * flashchip; \
flashchip->chip_size = FLASH_SIZE_16MBYTE
#define FLASH_SAFEMODE_LEAVE() \
flashchip->chip_size = flash_rom_get_size_byte(); \
} while(0)
/****************************************************************************** /******************************************************************************
* ROM Function definition * ROM Function definition
* Note: It is unsafe to use ROM function, but it may efficient. * Note: It is unsafe to use ROM function, but it may efficient.
* SPIEraseSector * SPIEraseSector
* unknown SPIEraseSector(uint16 sec); * SpiFlashOpResult SPIEraseSector(uint16 sec);
* The 1st parameter is flash sector number. * The 1st parameter is flash sector number.
* Note: Must disable cache read before using it.
* SPIRead (Unsafe) * SPIRead
* unknown SPIRead(uint32_t src_addr, uint32_t *des_addr, uint32_t size); * SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t *des_addr, uint32_t size);
* The 1st parameter is source addresses. * The 1st parameter is source addresses.
* The 2nd parameter is destination addresses. * The 2nd parameter is destination addresses.
* The 3rd parameter is size. * The 3rd parameter is size.
* Note: Sometimes it have no effect, may be need a delay or other option(lock or unlock, etc.) with known reason. * Note: Must disable cache read before using it.
* SPIWrite (Unsafe) * SPIWrite
* unknown SPIWrite(uint32_t des_addr, uint32_t *src_addr, uint32_t size); * SpiFlashOpResult SPIWrite(uint32_t des_addr, uint32_t *src_addr, uint32_t size);
* The 1st parameter is destination addresses. * The 1st parameter is destination addresses.
* The 2nd parameter is source addresses. * The 2nd parameter is source addresses.
* The 3rd parameter is size. * The 3rd parameter is size.
* Note: Sometimes it have no effect, may be need a delay or other option(lock or unlock, etc.) with known reason. * Note: Must disable cache read before using it.
*******************************************************************************/ *******************************************************************************/
typedef struct typedef struct
{ {
uint8_t unknown0; uint8_t header_magic;
uint8_t unknown1; uint8_t segment_count;
enum enum
{ {
MODE_QIO = 0, MODE_QIO = 0,
...@@ -55,20 +83,31 @@ typedef struct ...@@ -55,20 +83,31 @@ typedef struct
SIZE_64MBIT = 5, SIZE_64MBIT = 5,
SIZE_128MBIT = 6, SIZE_128MBIT = 6,
} size : 4; } size : 4;
uint32_t entry_point;
uint32_t memory_offset;
uint32_t segment_size;
} ICACHE_STORE_TYPEDEF_ATTR SPIFlashInfo; } ICACHE_STORE_TYPEDEF_ATTR SPIFlashInfo;
SPIFlashInfo flash_get_info(void); uint32_t flash_detect_size_byte(void);
uint8_t flash_get_size(void); uint32_t flash_safe_get_size_byte(void);
uint32_t flash_get_size_byte(void); uint16_t flash_safe_get_sec_num(void);
bool flash_set_size(uint8_t); SpiFlashOpResult flash_safe_read(uint32 src_addr, uint32 *des_addr, uint32 size);
bool flash_set_size_byte(uint32_t); SpiFlashOpResult flash_safe_write(uint32 des_addr, uint32 *src_addr, uint32 size);
uint16_t flash_get_sec_num(void); SpiFlashOpResult flash_safe_erase_sector(uint16 sec);
uint8_t flash_get_mode(void); SPIFlashInfo flash_rom_getinfo(void);
uint32_t flash_get_speed(void); uint8_t flash_rom_get_size_type(void);
uint32_t flash_rom_get_size_byte(void);
bool flash_rom_set_size_type(uint8_t);
bool flash_rom_set_size_byte(uint32_t);
uint16_t flash_rom_get_sec_num(void);
uint8_t flash_rom_get_mode(void);
uint32_t flash_rom_get_speed(void);
bool flash_init_data_written(void); bool flash_init_data_written(void);
bool flash_init_data_default(void); bool flash_init_data_default(void);
bool flash_init_data_blank(void); bool flash_init_data_blank(void);
bool flash_self_destruct(void); bool flash_self_destruct(void);
uint8_t byte_of_aligned_array(const uint8_t* aligned_array, uint32_t index); uint8_t byte_of_aligned_array(const uint8_t* aligned_array, uint32_t index);
// uint8_t flash_rom_get_checksum(void);
// uint8_t flash_rom_calc_checksum(void);
#endif // __FLASH_API_H__ #endif // __FLASH_API_H__
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
#define fs_format myspiffs_format #define fs_format myspiffs_format
#define fs_check myspiffs_check #define fs_check myspiffs_check
#define fs_rename myspiffs_rename #define fs_rename myspiffs_rename
#define fs_size myspiffs_size
#define FS_NAME_MAX_LENGTH SPIFFS_OBJ_NAME_LEN #define FS_NAME_MAX_LENGTH SPIFFS_OBJ_NAME_LEN
......
...@@ -160,11 +160,14 @@ int myspiffs_error( int fd ){ ...@@ -160,11 +160,14 @@ int myspiffs_error( int fd ){
return SPIFFS_errno(&fs); return SPIFFS_errno(&fs);
} }
void myspiffs_clearerr( int fd ){ void myspiffs_clearerr( int fd ){
fs.errno = SPIFFS_OK; SPIFFS_clearerr(&fs);
} }
int myspiffs_rename( const char *old, const char *newname ){ int myspiffs_rename( const char *old, const char *newname ){
return SPIFFS_rename(&fs, (char *)old, (char *)newname); return SPIFFS_rename(&fs, (char *)old, (char *)newname);
} }
size_t myspiffs_size( int fd ){
return SPIFFS_size(&fs, (spiffs_file)fd);
}
#if 0 #if 0
void test_spiffs() { void test_spiffs() {
char buf[12]; char buf[12];
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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