diff --git a/README.md b/README.md
index d388b0a8..d343075c 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
# **NodeMCU** #
version 0.9.5
+[![Join the chat at https://gitter.im/nodemcu/nodemcu-firmware](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nodemcu/nodemcu-firmware?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/nodemcu/nodemcu-firmware.svg)](https://travis-ci.org/nodemcu/nodemcu-firmware) [![Download](https://img.shields.io/badge/download-~400k-orange.svg)](https://github.com/nodemcu/nodemcu-firmware/releases/latest)
###A lua based firmware for wifi-soc esp8266
@@ -33,6 +34,10 @@ Tencent QQ group: 309957875
- cross compiler (done)
# Change log
+2015-03-15
+bugs fixed: #239, #273.
+reduce coap module memory usage, add coap module to default built.
+
2015-03-11
fix bugs of spiffs.
build both float and integer version [latest releases](https://github.com/nodemcu/nodemcu-firmware/releases/latest).
@@ -413,3 +418,25 @@ They'll be available as `u8g.` in Lua.
-- first LED green, second LED white
ws2812.writergb(4, string.char(0, 255, 0, 255, 255, 255))
```
+
+####coap client and server
+```lua
+-- use copper addon for firefox
+cs=coap.Server()
+cs:listen(5683)
+
+myvar=1
+cs:var("myvar") -- get coap://192.168.18.103:5683/v1/v/myvar will return the value of myvar: 1
+
+-- function should tack one string, return one string.
+function myfun(payload)
+ print("myfun called")
+ respond = "hello"
+ return respond
+end
+cs:func("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun
+
+cc = coap.Client()
+cc:get(coap.CON, "coap://192.168.18.100:5683/.well-known/core")
+cc:post(coap.NON, "coap://192.168.18.100:5683/", "Hello")
+```
\ No newline at end of file
diff --git a/app/coap/coap.c b/app/coap/coap.c
index 6dded680..af431d76 100644
--- a/app/coap/coap.c
+++ b/app/coap/coap.c
@@ -76,7 +76,7 @@ int coap_parseToken(coap_buffer_t *tokbuf, const coap_header_t *hdr, const uint8
else
if (hdr->tkl <= 8)
{
- if (4 + hdr->tkl > buflen)
+ if (4U + hdr->tkl > buflen)
return COAP_ERR_TOKEN_TOO_SHORT; // tok bigger than packet
tokbuf->p = buf+4; // past header
tokbuf->len = hdr->tkl;
@@ -93,7 +93,7 @@ int coap_buildToken(const coap_buffer_t *tokbuf, const coap_header_t *hdr, uint8
{
// inject token
uint8_t *p;
- if (buflen < 4 + hdr->tkl)
+ if (buflen < (4U + hdr->tkl))
return COAP_ERR_BUFFER_TOO_SMALL;
p = buf + 4;
if ((hdr->tkl > 0) && (hdr->tkl != tokbuf->len))
@@ -102,7 +102,7 @@ int coap_buildToken(const coap_buffer_t *tokbuf, const coap_header_t *hdr, uint8
if (hdr->tkl > 0)
c_memcpy(p, tokbuf->p, hdr->tkl);
- // http://tools.ietf.org/html/draft-ietf-core-coap-18#section-3.1
+ // http://tools.ietf.org/html/rfc7252#section-3.1
// inject options
return hdr->tkl;
}
@@ -111,8 +111,8 @@ int coap_buildToken(const coap_buffer_t *tokbuf, const coap_header_t *hdr, uint8
int coap_parseOption(coap_option_t *option, uint16_t *running_delta, const uint8_t **buf, size_t buflen)
{
const uint8_t *p = *buf;
- uint16_t len, delta;
uint8_t headlen = 1;
+ uint16_t len, delta;
if (buflen < headlen) // too small
return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER;
@@ -179,14 +179,14 @@ int coap_parseOption(coap_option_t *option, uint16_t *running_delta, const uint8
return 0;
}
-// http://tools.ietf.org/html/draft-ietf-core-coap-18#section-3.1
+// http://tools.ietf.org/html/rfc7252#section-3.1
int coap_parseOptionsAndPayload(coap_option_t *options, uint8_t *numOptions, coap_buffer_t *payload, const coap_header_t *hdr, const uint8_t *buf, size_t buflen)
{
size_t optionIndex = 0;
+ uint16_t delta = 0;
const uint8_t *p = buf + 4 + hdr->tkl;
const uint8_t *end = buf + buflen;
int rc;
- uint16_t delta = 0;
if (p > end)
return COAP_ERR_OPTION_OVERRUNS_PACKET; // out of bounds
@@ -215,7 +215,7 @@ int coap_parseOptionsAndPayload(coap_option_t *options, uint8_t *numOptions, coa
return 0;
}
-int coap_buildOptionHeader(unsigned short optDelta, size_t length, uint8_t *buf, size_t buflen)
+int coap_buildOptionHeader(uint32_t optDelta, size_t length, uint8_t *buf, size_t buflen)
{
int n = 0;
uint8_t *p = buf;
@@ -298,7 +298,7 @@ int coap_parse(coap_packet_t *pkt, const uint8_t *buf, size_t buflen)
}
// options are always stored consecutively, so can return a block with same option num
-const coap_option_t * coap_findOptions(const coap_packet_t *pkt, uint8_t num, uint8_t *count)
+const coap_option_t *coap_findOptions(const coap_packet_t *pkt, uint8_t num, uint8_t *count)
{
// FIXME, options is always sorted, can find faster than this
size_t i;
@@ -352,7 +352,7 @@ int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt)
uint16_t optDelta = 0;
int rc = 0;
- if (p-buf > *buflen)
+ if (((size_t)(p-buf)) > *buflen)
return COAP_ERR_BUFFER_TOO_SMALL;
optDelta = pkt->opts[i].num - running_delta;
@@ -381,17 +381,17 @@ int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt)
return 0;
}
-void coap_option_nibble(uint16_t value, uint8_t *nibble)
+void coap_option_nibble(uint32_t value, uint8_t *nibble)
{
if (value<13)
{
*nibble = (0xFF & value);
}
else
- if (((uint32_t)value)<=0xFF+13)
+ if (value<=0xFF+13)
{
*nibble = 13;
- } else if (((uint32_t)value) -269 <=0xFFFF)
+ } else if (value<=0xFFFF+269)
{
*nibble = 14;
}
@@ -405,7 +405,7 @@ int coap_make_response(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const uint
pkt->hdr.code = rspcode;
pkt->hdr.id[0] = msgid_hi;
pkt->hdr.id[1] = msgid_lo;
- pkt->numopts = 0;
+ pkt->numopts = 1;
// need token in response
if (tok) {
@@ -442,7 +442,7 @@ unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val) {
return n;
}
-static uint8_t _token_data[4]={'n','o','d','e'};
+static uint8_t _token_data[4] = {'n','o','d','e'};
coap_buffer_t the_token = { _token_data, 4 };
static unsigned short message_id;
diff --git a/app/coap/coap.h b/app/coap/coap.h
index 1c8827a6..3862f57b 100644
--- a/app/coap/coap.h
+++ b/app/coap/coap.h
@@ -18,13 +18,15 @@ extern "C" {
#define COAP_RESPONSE_CLASS(C) (((C) >> 5) & 0xFF)
-// http://tools.ietf.org/html/draft-ietf-core-coap-18#section-3
+//http://tools.ietf.org/html/rfc7252#section-3
typedef struct
{
- uint8_t ver;
- uint8_t t;
- uint8_t tkl;
- uint8_t code;
+ uint8_t ver; /* CoAP version number */
+ uint8_t t; /* CoAP Message Type */
+ uint8_t tkl; /* Token length: indicates length of the Token field */
+ uint8_t code; /* CoAP status code. Can be request (0.xx), success reponse (2.xx),
+ * client error response (4.xx), or rever error response (5.xx)
+ * For possible values, see http://tools.ietf.org/html/rfc7252#section-12.1 */
uint8_t id[2];
} coap_header_t;
@@ -42,23 +44,24 @@ typedef struct
typedef struct
{
- uint8_t num;
- coap_buffer_t buf;
+ uint8_t num; /* Option number. See http://tools.ietf.org/html/rfc7252#section-5.10 */
+ coap_buffer_t buf; /* Option value */
} coap_option_t;
typedef struct
{
- coap_header_t hdr;
- coap_buffer_t tok;
- uint8_t numopts;
- coap_option_t opts[MAXOPT];
- coap_buffer_t payload;
- coap_rw_buffer_t scratch; // scratch->p = malloc(...) , and free it when done.
+ coap_header_t hdr; /* Header of the packet */
+ coap_buffer_t tok; /* Token value, size as specified by hdr.tkl */
+ uint8_t numopts; /* Number of options */
+ coap_option_t opts[MAXOPT]; /* Options of the packet. For possible entries see
+ * http://tools.ietf.org/html/rfc7252#section-5.10 */
+ coap_buffer_t payload; /* Payload carried by the packet */
+ coap_rw_buffer_t content; // content->p = malloc(...) , and free it when done.
} coap_packet_t;
/////////////////////////////////////////
-//http://tools.ietf.org/html/draft-ietf-core-coap-18#section-12.2
+//http://tools.ietf.org/html/rfc7252#section-12.2
typedef enum
{
COAP_OPTION_IF_MATCH = 1,
@@ -78,7 +81,7 @@ typedef enum
COAP_OPTION_PROXY_SCHEME = 39
} coap_option_num_t;
-//http://tools.ietf.org/html/draft-ietf-core-coap-18#section-12.1.1
+//http://tools.ietf.org/html/rfc7252#section-12.1.1
typedef enum
{
COAP_METHOD_GET = 1,
@@ -87,7 +90,7 @@ typedef enum
COAP_METHOD_DELETE = 4
} coap_method_t;
-//http://tools.ietf.org/html/draft-ietf-core-coap-18#section-12.1.1
+//http://tools.ietf.org/html/rfc7252#section-12.1.1
typedef enum
{
COAP_TYPE_CON = 0,
@@ -96,8 +99,8 @@ typedef enum
COAP_TYPE_RESET = 3
} coap_msgtype_t;
-//http://tools.ietf.org/html/draft-ietf-core-coap-18#section-5.2
-//http://tools.ietf.org/html/draft-ietf-core-coap-18#section-12.1.2
+//http://tools.ietf.org/html/rfc7252#section-5.2
+//http://tools.ietf.org/html/rfc7252#section-12.1.2
#define MAKE_RSPCODE(clas, det) ((clas << 5) | (det))
typedef enum
{
@@ -107,7 +110,7 @@ typedef enum
COAP_RSPCODE_CHANGED = MAKE_RSPCODE(2, 4)
} coap_responsecode_t;
-//http://tools.ietf.org/html/draft-ietf-core-coap-18#section-12.3
+//http://tools.ietf.org/html/rfc7252#section-12.3
typedef enum
{
COAP_CONTENTTYPE_NONE = -1, // bodge to allow us not to send option block
@@ -155,15 +158,21 @@ struct coap_luser_entry{
coap_luser_entry *next;
};
-struct coap_endpoint_t
-{
- coap_method_t method;
- coap_endpoint_func handler;
- const coap_endpoint_path_t *path;
- const char *core_attr;
- coap_luser_entry *user_entry;
+struct coap_endpoint_t{
+ coap_method_t method; /* (i.e. POST, PUT or GET) */
+ coap_endpoint_func handler; /* callback function which handles this
+ * type of endpoint (and calls
+ * coap_make_response() at some point) */
+ const coap_endpoint_path_t *path; /* path towards a resource (i.e. foo/bar/) */
+ const char *core_attr; /* the 'ct' attribute, as defined in RFC7252, section 7.2.1.:
+ * "The Content-Format code "ct" attribute
+ * provides a hint about the
+ * Content-Formats this resource returns."
+ * (Section 12.3. lists possible ct values.) */
+ coap_luser_entry *user_entry;
};
+
///////////////////////
void coap_dumpPacket(coap_packet_t *pkt);
int coap_parse(coap_packet_t *pkt, const uint8_t *buf, size_t buflen);
@@ -173,11 +182,11 @@ int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt);
void coap_dump(const uint8_t *buf, size_t buflen, bool bare);
int coap_make_response(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const uint8_t *content, size_t content_len, uint8_t msgid_hi, uint8_t msgid_lo, const coap_buffer_t* tok, coap_responsecode_t rspcode, coap_content_type_t content_type);
int coap_handle_req(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt);
-void coap_option_nibble(uint16_t value, uint8_t *nibble);
+void coap_option_nibble(uint32_t value, uint8_t *nibble);
void coap_setup(void);
void endpoint_setup(void);
-int coap_buildOptionHeader(unsigned short optDelta, size_t length, uint8_t *buf, size_t buflen);
+int coap_buildOptionHeader(uint32_t optDelta, size_t length, uint8_t *buf, size_t buflen);
#ifdef __cplusplus
}
diff --git a/app/coap/coap_client.c b/app/coap/coap_client.c
index 37a1a5f0..63caf074 100644
--- a/app/coap/coap_client.c
+++ b/app/coap/coap_client.c
@@ -11,6 +11,8 @@ void coap_client_response_handler(char *data, unsigned short len, unsigned short
{
NODE_DBG("coap_client_response_handler is called.\n");
coap_packet_t pkt;
+ pkt.content.p = NULL;
+ pkt.content.len = 0;
int rc;
if (0 != (rc = coap_parse(&pkt, data, len))){
diff --git a/app/coap/coap_client.h b/app/coap/coap_client.h
index 5559adfe..7f0a457b 100644
--- a/app/coap/coap_client.h
+++ b/app/coap/coap_client.h
@@ -1,11 +1,11 @@
-#ifndef _COAP_SERVER_H
-#define _COAP_SERVER_H 1
+#ifndef _COAP_CLIENT_H
+#define _COAP_CLIENT_H 1
#ifdef __cplusplus
extern "C" {
#endif
-size_t coap_server_respond(char *data, unsigned short len, unsigned short size);
+void coap_client_response_handler(char *data, unsigned short len, unsigned short size, const uint32_t ip, const uint32_t port);
#ifdef __cplusplus
}
diff --git a/app/coap/coap_server.c b/app/coap/coap_server.c
index d87bd8f7..cbec01f9 100644
--- a/app/coap/coap_server.c
+++ b/app/coap/coap_server.c
@@ -1,53 +1,60 @@
#include "user_config.h"
#include "c_types.h"
+#include "c_stdlib.h"
#include "coap.h"
-size_t coap_server_respond(char *data, unsigned short len, unsigned short size)
+size_t coap_server_respond(char *req, unsigned short reqlen, char *rsp, unsigned short rsplen)
{
NODE_DBG("coap_server_respond is called.\n");
- if(len>size){
- NODE_DBG("len:%d, size:%d\n",len,size);
- return 0;
- }
- size_t rsplen = size;
+ size_t rlen = rsplen;
coap_packet_t pkt;
+ pkt.content.p = NULL;
+ pkt.content.len = 0;
uint8_t scratch_raw[4];
coap_rw_buffer_t scratch_buf = {scratch_raw, sizeof(scratch_raw)};
int rc;
#ifdef COAP_DEBUG
NODE_DBG("Received: ");
- coap_dump(data, len, true);
+ coap_dump(req, reqlen, true);
NODE_DBG("\n");
#endif
- if (0 != (rc = coap_parse(&pkt, data, len))){
+ if (0 != (rc = coap_parse(&pkt, req, reqlen))){
NODE_DBG("Bad packet rc=%d\n", rc);
return 0;
}
else
{
coap_packet_t rsppkt;
+ rsppkt.content.p = NULL;
+ rsppkt.content.len = 0;
#ifdef COAP_DEBUG
coap_dumpPacket(&pkt);
#endif
coap_handle_req(&scratch_buf, &pkt, &rsppkt);
- if (0 != (rc = coap_build(data, &rsplen, &rsppkt))){
+ if (0 != (rc = coap_build(rsp, &rlen, &rsppkt))){
NODE_DBG("coap_build failed rc=%d\n", rc);
- return 0;
+ // return 0;
+ rlen = 0;
}
else
{
#ifdef COAP_DEBUG
NODE_DBG("Responding: ");
- coap_dump(data, rsplen, true);
+ coap_dump(rsp, rlen, true);
NODE_DBG("\n");
#endif
#ifdef COAP_DEBUG
coap_dumpPacket(&rsppkt);
#endif
}
- return rsplen;
+ if(rsppkt.content.p){
+ c_free(rsppkt.content.p);
+ rsppkt.content.p = NULL;
+ rsppkt.content.len = 0;
+ }
+ return rlen;
}
}
diff --git a/app/coap/coap_server.h b/app/coap/coap_server.h
index 5559adfe..7eb023ec 100644
--- a/app/coap/coap_server.h
+++ b/app/coap/coap_server.h
@@ -5,7 +5,7 @@
extern "C" {
#endif
-size_t coap_server_respond(char *data, unsigned short len, unsigned short size);
+size_t coap_server_respond(char *req, unsigned short reqlen, char *rsp, unsigned short rsplen);
#ifdef __cplusplus
}
diff --git a/app/coap/endpoints.c b/app/coap/endpoints.c
index a3d2d9d6..1d7d48bb 100644
--- a/app/coap/endpoints.c
+++ b/app/coap/endpoints.c
@@ -1,5 +1,6 @@
#include "c_stdio.h"
#include "c_string.h"
+#include "c_stdlib.h"
#include "coap.h"
#include "lua.h"
@@ -8,20 +9,24 @@
#include "os_type.h"
-static char rsp[MAX_PAYLOAD_SIZE] = "";
-const uint16_t rsplen = MAX_PAYLOAD_SIZE;
-void build_well_known_rsp(void);
+void build_well_known_rsp(char *rsp, uint16_t rsplen);
void endpoint_setup(void)
{
coap_setup();
- build_well_known_rsp();
}
static const coap_endpoint_path_t path_well_known_core = {2, {".well-known", "core"}};
static int handle_get_well_known_core(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
{
- return coap_make_response(scratch, outpkt, (const uint8_t *)rsp, c_strlen(rsp), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_APPLICATION_LINKFORMAT);
+ outpkt->content.p = (uint8_t *)c_zalloc(MAX_PAYLOAD_SIZE); // this should be free-ed when outpkt is built in coap_server_respond()
+ if(outpkt->content.p == NULL){
+ NODE_DBG("not enough memory\n");
+ return COAP_ERR_BUFFER_TOO_SMALL;
+ }
+ outpkt->content.len = MAX_PAYLOAD_SIZE;
+ build_well_known_rsp(outpkt->content.p, outpkt->content.len);
+ return coap_make_response(scratch, outpkt, (const uint8_t *)outpkt->content.p, c_strlen(outpkt->content.p), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_APPLICATION_LINKFORMAT);
}
static const coap_endpoint_path_t path_variable = {2, {"v1", "v"}};
@@ -29,6 +34,7 @@ static int handle_get_variable(const coap_endpoint_t *ep, coap_rw_buffer_t *scra
{
const coap_option_t *opt;
uint8_t count;
+ int n;
if (NULL != (opt = coap_findOptions(inpkt, COAP_OPTION_URI_PATH, &count)))
{
if ((count != ep->path->count ) && (count != ep->path->count + 1)) // +1 for /f/[function], /v/[variable]
@@ -54,14 +60,15 @@ static int handle_get_variable(const coap_endpoint_t *ep, coap_rw_buffer_t *scra
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
if(c_strlen(h->name))
{
+ n = lua_gettop(h->L);
lua_getglobal(h->L, h->name);
if (!lua_isnumber(h->L, -1)) {
NODE_DBG ("should be a number.\n");
- lua_pop(h->L, 1);
+ lua_settop(h->L, n);
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
} else {
const char *res = lua_tostring(h->L,-1);
- lua_pop(h->L, 1);
+ lua_settop(h->L, n);
return coap_make_response(scratch, outpkt, (const uint8_t *)res, c_strlen(res), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
}
}
@@ -84,6 +91,7 @@ static int handle_post_function(const coap_endpoint_t *ep, coap_rw_buffer_t *scr
{
const coap_option_t *opt;
uint8_t count;
+ int n;
if (NULL != (opt = coap_findOptions(inpkt, COAP_OPTION_URI_PATH, &count)))
{
if ((count != ep->path->count ) && (count != ep->path->count + 1)) // +1 for /f/[function], /v/[variable]
@@ -111,10 +119,11 @@ static int handle_post_function(const coap_endpoint_t *ep, coap_rw_buffer_t *scr
if(c_strlen(h->name))
{
+ n = lua_gettop(h->L);
lua_getglobal(h->L, h->name);
if (lua_type(h->L, -1) != LUA_TFUNCTION) {
NODE_DBG ("should be a function\n");
- lua_pop(h->L, 1);
+ lua_settop(h->L, n);
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
} else {
lua_pushlstring(h->L, inpkt->payload.p, inpkt->payload.len); // make sure payload.p is filled with '\0' after payload.len, or use lua_pushlstring
@@ -125,14 +134,17 @@ static int handle_post_function(const coap_endpoint_t *ep, coap_rw_buffer_t *scr
size_t len = 0;
const char *ret = luaL_checklstring( h->L, -1, &len );
if(len > MAX_PAYLOAD_SIZE){
+ lua_settop(h->L, n);
luaL_error( h->L, "return string:tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
}
NODE_DBG((char *)ret);
NODE_DBG("\n");
+ lua_settop(h->L, n);
return coap_make_response(scratch, outpkt, ret, len, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
}
} else {
+ lua_settop(h->L, n);
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
}
}
@@ -204,13 +216,13 @@ const coap_endpoint_t endpoints[] =
{(coap_method_t)0, NULL, NULL, NULL, NULL}
};
-void build_well_known_rsp(void)
+void build_well_known_rsp(char *rsp, uint16_t rsplen)
{
const coap_endpoint_t *ep = endpoints;
int i;
uint16_t len = rsplen;
- c_memset(rsp, 0, sizeof(rsp));
+ c_memset(rsp, 0, len);
len--; // Null-terminated string
diff --git a/app/coap/pdu.c b/app/coap/pdu.c
index 8313146c..e32f028d 100644
--- a/app/coap/pdu.c
+++ b/app/coap/pdu.c
@@ -24,6 +24,8 @@ coap_pdu_t * coap_new_pdu(void) {
c_free(pdu);
return NULL;
}
+ pdu->pkt->content.p = NULL;
+ pdu->pkt->content.len = 0;
pdu->msg.p = (uint8_t *)c_zalloc(MAX_REQUEST_SIZE+1); // +1 for string '\0'
if(!pdu->msg.p){
diff --git a/app/include/user_config.h b/app/include/user_config.h
index c1a9805c..a91aa179 100644
--- a/app/include/user_config.h
+++ b/app/include/user_config.h
@@ -10,6 +10,7 @@
// #define FLASH_8M
// #define FLASH_16M
#define FLASH_AUTOSIZE
+#define FLASH_SAFE_API
// #define DEVELOP_VERSION
#define FULL_VERSION_FOR_USER
diff --git a/app/include/user_modules.h b/app/include/user_modules.h
index a21cee19..103b004f 100644
--- a/app/include/user_modules.h
+++ b/app/include/user_modules.h
@@ -27,7 +27,7 @@
#define LUA_USE_MODULES_OW
#define LUA_USE_MODULES_BIT
#define LUA_USE_MODULES_MQTT
-// #define LUA_USE_MODULES_COAP // need about 4k more ram for now
+#define LUA_USE_MODULES_COAP
#define LUA_USE_MODULES_U8G
#define LUA_USE_MODULES_WS2812
#endif /* LUA_USE_MODULES */
diff --git a/app/include/user_version.h b/app/include/user_version.h
index ed2b0d6d..1576fbe3 100644
--- a/app/include/user_version.h
+++ b/app/include/user_version.h
@@ -7,6 +7,6 @@
#define NODE_VERSION_INTERNAL 0U
#define NODE_VERSION "NodeMCU 0.9.5"
-#define BUILD_DATE "build 20150311"
+#define BUILD_DATE "build 20150315"
#endif /* __USER_VERSION_H__ */
diff --git a/app/libc/c_stdio.c b/app/libc/c_stdio.c
index 03e64581..a8e0956f 100644
--- a/app/libc/c_stdio.c
+++ b/app/libc/c_stdio.c
@@ -63,7 +63,7 @@ int c_stderr = 1001;
#define ENDIAN_LITTLE 1234
#define ENDIAN_BIG 4321
#define ENDIAN_PDP 3412
-#define ENDIAN ENDIAN_BIG
+#define ENDIAN ENDIAN_LITTLE
/* $Id: strichr.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
diff --git a/app/lua/lauxlib.c b/app/lua/lauxlib.c
index 00e740be..e5c89ad5 100644
--- a/app/lua/lauxlib.c
+++ b/app/lua/lauxlib.c
@@ -659,13 +659,19 @@ typedef struct LoadFSF {
static const char *getFSF (lua_State *L, void *ud, size_t *size) {
LoadFSF *lf = (LoadFSF *)ud;
(void)L;
+
+ if (L == NULL && size == NULL) // Direct mode check
+ return NULL;
+
if (lf->extraline) {
lf->extraline = 0;
*size = 1;
return "\n";
}
+
if (fs_eof(lf->f)) return NULL;
*size = fs_read(lf->f, lf->buff, sizeof(lf->buff));
+
return (*size > 0) ? lf->buff : NULL;
}
diff --git a/app/modules/coap.c b/app/modules/coap.c
index 2afb9b54..8e1ba6c0 100644
--- a/app/modules/coap.c
+++ b/app/modules/coap.c
@@ -37,20 +37,20 @@ static void coap_received(void *arg, char *pdata, unsigned short len)
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'
+ // 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;
- } else {
- c_memcpy(buf, pdata, len);
}
+ // c_memcpy(buf, pdata, len);
- size_t rsplen = coap_server_respond(buf, len, MAX_MESSAGE_SIZE+1);
+ 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));
+ // c_memset(buf, 0, sizeof(buf));
}
static void coap_sent(void *arg)
@@ -227,26 +227,19 @@ static void coap_response_handler(void *arg, char *pdata, unsigned short len)
struct espconn *pesp_conn = arg;
coap_packet_t pkt;
- static uint8_t buf[MAX_MESSAGE_SIZE+1] = {0}; // +1 for string '\0'
+ 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
- static int n = 0;
int rc;
- if ((len == 1460) && (1460 <= MAX_MESSAGE_SIZE)){
- c_memcpy(buf, pdata, len); // max length is 1460, another part of data is coming in next callback
- n = len;
+ if( len > MAX_MESSAGE_SIZE )
+ {
+ NODE_DBG("Request Entity Too Large.\n"); // NOTE: should response 4.13 to client...
return;
- } else {
- if( len > MAX_MESSAGE_SIZE )
- {
- NODE_DBG("Request Entity Too Large.\n"); // NOTE: should response 4.13 to client...
- c_memset(buf, 0, sizeof(buf)); // wipe prev data
- n = 0;
- return;
- }
- c_memcpy(buf + n, pdata, len);
- len += n; // more than 1460
}
+ c_memcpy(buf, pdata, len);
if (0 != (rc = coap_parse(&pkt, buf, len))){
NODE_DBG("Bad packet rc=%d\n", rc);
@@ -306,8 +299,7 @@ end:
if(pesp_conn->proto.udp->remote_port || pesp_conn->proto.udp->local_port)
espconn_delete(pesp_conn);
}
- c_memset(buf, 0, sizeof(buf));
- n = 0;
+ // c_memset(buf, 0, sizeof(buf));
}
// Lua: client:request( [CON], uri, [payload] )
@@ -431,7 +423,6 @@ static int coap_request( lua_State* L, coap_method_t m )
extern coap_luser_entry *variable_entry;
extern coap_luser_entry *function_entry;
-extern void build_well_known_rsp(void);
// Lua: coap:var/func( string )
static int coap_regist( lua_State* L, const char* mt, int isvar )
{
@@ -466,8 +457,6 @@ static int coap_regist( lua_State* L, const char* mt, int isvar )
h->L = L;
h->name = name;
- build_well_known_rsp(); // rebuild .well-known
-
NODE_DBG("coap_regist is called.\n");
return 0;
}
diff --git a/app/modules/node.c b/app/modules/node.c
index 0384d798..caf2af42 100644
--- a/app/modules/node.c
+++ b/app/modules/node.c
@@ -29,7 +29,7 @@
static int node_restart( lua_State* L )
{
system_restart();
- return 0;
+ return 0;
}
// Lua: dsleep( us, option )
@@ -56,7 +56,7 @@ static int node_deepsleep( lua_State* L )
else
system_deep_sleep( us );
}
- return 0;
+ return 0;
}
// Lua: dsleep_set_options
@@ -80,10 +80,14 @@ static int node_info( lua_State* L )
lua_pushinteger(L, NODE_VERSION_REVISION);
lua_pushinteger(L, system_get_chip_id()); // chip id
lua_pushinteger(L, spi_flash_get_id()); // flash id
- lua_pushinteger(L, flash_get_size_byte() / 1024); // flash size in KB
- lua_pushinteger(L, flash_get_mode());
- lua_pushinteger(L, flash_get_speed());
- return 8;
+#if defined(FLASH_SAFE_API)
+ lua_pushinteger(L, flash_safe_get_size_byte() / 1024); // flash size in KB
+#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;
}
// Lua: chipid()
@@ -91,7 +95,7 @@ static int node_chipid( lua_State* L )
{
uint32_t id = system_get_chip_id();
lua_pushinteger(L, id);
- return 1;
+ return 1;
}
// Lua: readvdd33()
static int node_readvdd33( lua_State* L )
@@ -106,24 +110,23 @@ static int node_flashid( lua_State* L )
{
uint32_t id = spi_flash_get_id();
lua_pushinteger( L, id );
- return 1;
+ return 1;
}
// Lua: flashsize()
static int node_flashsize( lua_State* L )
{
- //uint32_t sz = 0;
- //if(lua_type(L, 1) == LUA_TNUMBER)
- //{
- // sz = luaL_checkinteger(L, 1);
- // if(sz > 0)
- // {
- // flash_set_size_byte(sz);
- // }
- //}
- uint32_t sz = flash_get_size_byte();
+ if (lua_type(L, 1) == LUA_TNUMBER)
+ {
+ flash_rom_set_size_byte(luaL_checkinteger(L, 1));
+ }
+#if defined(FLASH_SAFE_API)
+ uint32_t sz = flash_safe_get_size_byte();
+#else
+ uint32_t sz = flash_rom_get_size_byte();
+#endif // defined(FLASH_SAFE_API)
lua_pushinteger( L, sz );
- return 1;
+ return 1;
}
// Lua: heap()
@@ -131,7 +134,7 @@ static int node_heap( lua_State* L )
{
uint32_t sz = system_get_free_heap_size();
lua_pushinteger(L, sz);
- return 1;
+ return 1;
}
static lua_State *gL = NULL;
@@ -146,7 +149,7 @@ static int node_led( lua_State* L )
if ( lua_isnumber(L, 1) )
{
low = lua_tointeger(L, 1);
- if ( low < 0 ){
+ if ( low < 0 ) {
return luaL_error( L, "wrong arg type" );
}
} else {
@@ -155,7 +158,7 @@ static int node_led( lua_State* L )
if ( lua_isnumber(L, 2) )
{
high = lua_tointeger(L, 2);
- if ( high < 0 ){
+ if ( high < 0 ) {
return luaL_error( L, "wrong arg type" );
}
} else {
@@ -163,14 +166,14 @@ static int node_led( lua_State* L )
}
led_high_count = (uint32_t)high / READLINE_INTERVAL;
led_low_count = (uint32_t)low / READLINE_INTERVAL;
- return 0;
+ return 0;
}
static int long_key_ref = LUA_NOREF;
static int short_key_ref = LUA_NOREF;
-void default_long_press(void *arg){
- if(led_high_count == 12 && led_low_count == 12){
+void default_long_press(void *arg) {
+ if (led_high_count == 12 && led_low_count == 12) {
led_low_count = led_high_count = 6;
} else {
led_low_count = led_high_count = 12;
@@ -180,32 +183,32 @@ void default_long_press(void *arg){
// 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();
}
-void key_long_press(void *arg){
+void key_long_press(void *arg) {
NODE_DBG("key_long_press is called.\n");
- if(long_key_ref == LUA_NOREF){
+ if (long_key_ref == LUA_NOREF) {
default_long_press(arg);
return;
}
- if(!gL)
+ if (!gL)
return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, long_key_ref);
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");
- if(short_key_ref == LUA_NOREF){
+ if (short_key_ref == LUA_NOREF) {
default_short_press(arg);
return;
}
- if(!gL)
+ if (!gL)
return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, short_key_ref);
- lua_call(gL, 0, 0);
+ lua_call(gL, 0, 0);
}
// Lua: key(type, function)
@@ -213,32 +216,32 @@ static int node_key( lua_State* L )
{
int *ref = NULL;
size_t sl;
-
+
const char *str = luaL_checklstring( L, 1, &sl );
if (str == NULL)
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;
- }else if(sl == 4 && c_strcmp(str, "long") == 0){
+ } else if (sl == 4 && c_strcmp(str, "long") == 0) {
ref = &long_key_ref;
- }else{
+ } else {
ref = &short_key_ref;
}
gL = L;
// 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
- if(*ref != LUA_NOREF)
+ if (*ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, *ref);
*ref = luaL_ref(L, LUA_REGISTRYINDEX);
} else { // unref the key press function
- if(*ref != LUA_NOREF)
+ if (*ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, *ref);
- *ref = LUA_NOREF;
+ *ref = LUA_NOREF;
}
- return 0;
+ return 0;
}
#endif
@@ -248,15 +251,15 @@ extern void dojob(lua_Load *load);
// Lua: input("string")
static int node_input( lua_State* L )
{
- size_t l=0;
+ size_t l = 0;
const char *s = luaL_checklstring(L, 1, &l);
if (s != NULL && l > 0 && l < LUA_MAXINPUT - 1)
{
lua_Load *load = &gLoad;
- if(load->line_position == 0){
+ if (load->line_position == 0) {
c_memcpy(load->line, s, l);
- load->line[l+1] = '\0';
- load->line_position = c_strlen(load->line)+1;
+ load->line[l + 1] = '\0';
+ load->line_position = c_strlen(load->line) + 1;
load->done = 1;
NODE_DBG("Get command:\n");
NODE_DBG(load->line); // buggy here
@@ -271,18 +274,18 @@ static int node_input( lua_State* L )
static int output_redir_ref = LUA_NOREF;
static int serial_debug = 1;
-void output_redirect(const char *str){
+void output_redirect(const char *str) {
// if(c_strlen(str)>=TX_BUFF_SIZE){
// NODE_ERR("output too long.\n");
// return;
// }
- if(output_redir_ref == LUA_NOREF || !gL){
+ if (output_redir_ref == LUA_NOREF || !gL) {
uart0_sendStr(str);
return;
}
- if(serial_debug!=0){
+ if (serial_debug != 0) {
uart0_sendStr(str);
}
@@ -296,15 +299,15 @@ static int node_output( lua_State* L )
{
gL = L;
// 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
- if(output_redir_ref != LUA_NOREF)
+ if (output_redir_ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref);
output_redir_ref = luaL_ref(L, LUA_REGISTRYINDEX);
} 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);
- output_redir_ref = LUA_NOREF;
+ output_redir_ref = LUA_NOREF;
serial_debug = 1;
return 0;
}
@@ -312,26 +315,26 @@ static int node_output( lua_State* L )
if ( lua_isnumber(L, 2) )
{
serial_debug = lua_tointeger(L, 2);
- if(serial_debug!=0)
+ if (serial_debug != 0)
serial_debug = 1;
} else {
serial_debug = 1; // default to 1
}
- return 0;
+ return 0;
}
static int writer(lua_State* L, const void* p, size_t size, void* u)
{
UNUSED(L);
int file_fd = *( (int *)u );
- if((FS_OPEN_OK - 1)==file_fd)
+ if ((FS_OPEN_OK - 1) == file_fd)
return 1;
- NODE_DBG("get fd:%d,size:%d\n",file_fd,size);
-
- if(size!=0 && (size!=fs_write(file_fd, (const char *)p, size)) )
+ NODE_DBG("get fd:%d,size:%d\n", file_fd, size);
+
+ if (size != 0 && (size != fs_write(file_fd, (const char *)p, size)) )
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;
}
@@ -343,45 +346,45 @@ static int node_compile( lua_State* L )
int file_fd = FS_OPEN_OK - 1;
size_t 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");
char output[FS_NAME_MAX_LENGTH];
c_strcpy(output, fname);
// 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");
- output[c_strlen(output)-2] = 'c';
- output[c_strlen(output)-1] = '\0';
+ output[c_strlen(output) - 2] = 'c';
+ output[c_strlen(output) - 1] = '\0';
NODE_DBG(output);
NODE_DBG("\n");
- if (luaL_loadfsfile(L,fname)!=0){
- return luaL_error(L, lua_tostring(L,-1));
+ if (luaL_loadfsfile(L, fname) != 0) {
+ return luaL_error(L, lua_tostring(L, -1));
}
- f = toproto(L,-1);
+ f = toproto(L, -1);
int stripping = 1; /* strip debug information? */
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");
}
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);
fs_flush(file_fd);
fs_close(file_fd);
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");
}
- 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");
}
@@ -391,7 +394,7 @@ static int node_compile( lua_State* L )
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
-const LUA_REG_TYPE node_map[] =
+const LUA_REG_TYPE node_map[] =
{
{ LSTRKEY( "restart" ), LFUNCVAL( node_restart ) },
{ LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) },
@@ -408,7 +411,7 @@ const LUA_REG_TYPE node_map[] =
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) },
{ LSTRKEY( "readvdd33" ), LFUNCVAL( node_readvdd33) },
{ LSTRKEY( "compile" ), LFUNCVAL( node_compile) },
-// Combined to dsleep(us, option)
+// Combined to dsleep(us, option)
// { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) },
#if LUA_OPTIMIZE_MEMORY > 0
diff --git a/app/platform/cpu_esp8266.h b/app/platform/cpu_esp8266.h
index 75a238dc..ec6440a7 100644
--- a/app/platform/cpu_esp8266.h
+++ b/app/platform/cpu_esp8266.h
@@ -30,7 +30,11 @@
#elif defined(FLASH_16M)
#define FLASH_SEC_NUM 0x1000
#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
#define FLASH_SEC_NUM 0x80
#endif
@@ -54,8 +58,14 @@
// SpiFlashOpResult spi_flash_erase_sector(uint16 sec);
// SpiFlashOpResult spi_flash_write(uint32 des_addr, uint32 *src_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_erase spi_flash_erase_sector
#define flash_read spi_flash_read
+#endif // defined(FLASH_SAFE_API)
#endif // #ifndef __CPU_ESP8266_H__
diff --git a/app/platform/flash_api.c b/app/platform/flash_api.c
index c4ce6f57..a648d91b 100644
--- a/app/platform/flash_api.c
+++ b/app/platform/flash_api.c
@@ -20,77 +20,154 @@ 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
};
-SPIFlashInfo flash_get_info(void)
+uint32_t flash_detect_size_byte(void)
{
- volatile SPIFlashInfo spi_flash_info ICACHE_STORE_ATTR;
- spi_flash_info = *((SPIFlashInfo *)(FLASH_MAP_START_ADDRESS));
- // spi_flash_read(0, (uint32 *)(& spi_flash_info), sizeof(spi_flash_info));
- return spi_flash_info;
-}
-
-uint8_t flash_get_size(void)
-{
- return flash_get_info().size;
-}
-
-uint32_t flash_get_size_byte(void)
-{
- uint32_t flash_size = 0;
- switch (flash_get_info().size)
+#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))
{
- case SIZE_2MBIT:
- // 2Mbit, 256kByte
- flash_size = 256 * 1024;
- break;
- case SIZE_4MBIT:
- // 4Mbit, 512kByte
- flash_size = 512 * 1024;
- break;
- case SIZE_8MBIT:
- // 8Mbit, 1MByte
- flash_size = 1 * 1024 * 1024;
- break;
- case SIZE_16MBIT:
- // 16Mbit, 2MByte
- flash_size = 2 * 1024 * 1024;
- break;
- case SIZE_32MBIT:
- // 32Mbit, 4MByte
- flash_size = 4 * 1024 * 1024;
- break;
- case SIZE_64MBIT:
- // 64Mbit, 8MByte
- flash_size = 8 * 1024 * 1024;
- break;
- case SIZE_128MBIT:
- // 128Mbit, 16MByte
- flash_size = 16 * 1024 * 1024;
- break;
- default:
- // Unknown flash size, fall back mode.
- flash_size = 512 * 1024;
- break;
+ 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;
}
-bool flash_set_size(uint8_t 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;
+ // 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;
+}
+
+uint8_t flash_rom_get_size_type(void)
+{
+ return flash_rom_getinfo().size;
+}
+
+uint32_t flash_rom_get_size_byte(void)
+{
+ static uint32_t flash_size = 0;
+ if (flash_size == 0)
+ {
+ switch (flash_rom_getinfo().size)
+ {
+ case SIZE_2MBIT:
+ // 2Mbit, 256kByte
+ flash_size = 256 * 1024;
+ break;
+ case SIZE_4MBIT:
+ // 4Mbit, 512kByte
+ flash_size = 512 * 1024;
+ break;
+ case SIZE_8MBIT:
+ // 8Mbit, 1MByte
+ flash_size = 1 * 1024 * 1024;
+ break;
+ case SIZE_16MBIT:
+ // 16Mbit, 2MByte
+ flash_size = 2 * 1024 * 1024;
+ break;
+ case SIZE_32MBIT:
+ // 32Mbit, 4MByte
+ flash_size = 4 * 1024 * 1024;
+ break;
+ case SIZE_64MBIT:
+ // 64Mbit, 8MByte
+ flash_size = 8 * 1024 * 1024;
+ break;
+ case SIZE_128MBIT:
+ // 128Mbit, 16MByte
+ flash_size = 16 * 1024 * 1024;
+ break;
+ default:
+ // Unknown flash size, fall back mode.
+ flash_size = 512 * 1024;
+ break;
+ }
+ }
+ return flash_size;
+}
+
+bool flash_rom_set_size_type(uint8_t size)
{
// 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;
- spi_flash_read(0, (uint32 *)data, sizeof(data));
- SPIFlashInfo *p_spi_flash_info = (SPIFlashInfo *)(data);
- p_spi_flash_info->size = size;
- spi_flash_erase_sector(0);
- spi_flash_write(0, (uint32 *)data, sizeof(data));
- //p_spi_flash_info = flash_get_info();
- //p_spi_flash_info->size = size;
+ if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE))
+ {
+ ((SPIFlashInfo *)(&data[0]))->size = size;
+ 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", size);
+ }
+ }
+ NODE_DBG("\nEND SET FLASH HEADER\n");
return true;
}
-bool flash_set_size_byte(uint32_t size)
+bool flash_rom_set_size_byte(uint32_t size)
{
// Dangerous, here are dinosaur infested!!!!!
// Reboot required!!!
@@ -102,27 +179,37 @@ bool flash_set_size_byte(uint32_t size)
case 256 * 1024:
// 2Mbit, 256kByte
flash_size = SIZE_2MBIT;
- flash_set_size(flash_size);
+ flash_rom_set_size_type(flash_size);
break;
case 512 * 1024:
// 4Mbit, 512kByte
flash_size = SIZE_4MBIT;
- flash_set_size(flash_size);
+ flash_rom_set_size_type(flash_size);
break;
case 1 * 1024 * 1024:
// 8Mbit, 1MByte
flash_size = SIZE_8MBIT;
- flash_set_size(flash_size);
+ flash_rom_set_size_type(flash_size);
break;
case 2 * 1024 * 1024:
// 16Mbit, 2MByte
flash_size = SIZE_16MBIT;
- flash_set_size(flash_size);
+ flash_rom_set_size_type(flash_size);
break;
case 4 * 1024 * 1024:
// 32Mbit, 4MByte
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;
default:
// Unknown flash size.
@@ -132,22 +219,22 @@ bool flash_set_size_byte(uint32_t size)
return result;
}
-uint16_t flash_get_sec_num(void)
+uint16_t flash_rom_get_sec_num(void)
{
//static uint16_t sec_num = 0;
- // return flash_get_size_byte() / (SPI_FLASH_SEC_SIZE);
- // c_printf("\nflash_get_size_byte()=%d\n", ( flash_get_size_byte() / (SPI_FLASH_SEC_SIZE) ));
+ // 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_get_size_byte() / (SPI_FLASH_SEC_SIZE) );
+ 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)
{
// Reserved for future use
@@ -163,10 +250,10 @@ uint8_t flash_get_mode(void)
return spi_flash_info.mode;
}
-uint32_t flash_get_speed(void)
+uint32_t flash_rom_get_speed(void)
{
uint32_t speed = 0;
- SPIFlashInfo spi_flash_info = flash_get_info();
+ SPIFlashInfo spi_flash_info = flash_rom_getinfo();
switch (spi_flash_info.speed)
{
case SPEED_40MHZ:
@@ -189,11 +276,55 @@ uint32_t flash_get_speed(void)
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)
{
// FLASH SEC - 4
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)
{
@@ -210,13 +341,23 @@ bool flash_init_data_default(void)
// Reboot required!!!
// It will init system data to default!
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;
}
}
+#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;
}
@@ -227,8 +368,13 @@ bool flash_init_data_blank(void)
// Reboot required!!!
// It will init system config to blank!
bool result = false;
- if ((SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_get_sec_num() - 2))) &&
- (SPI_FLASH_RESULT_OK == spi_flash_erase_sector((flash_get_sec_num() - 1))))
+#if defined(FLASH_SAFE_API)
+ 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;
}
@@ -254,3 +400,28 @@ uint8_t byte_of_aligned_array(const uint8_t *aligned_array, uint32_t index)
uint8_t *p = (uint8_t *) (&v);
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
diff --git a/app/platform/flash_api.h b/app/platform/flash_api.h
index 038553a2..ff276a83 100644
--- a/app/platform/flash_api.h
+++ b/app/platform/flash_api.h
@@ -4,34 +4,61 @@
#include "user_config.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
* Note: It is unsafe to use ROM function, but it may efficient.
* SPIEraseSector
- * unknown SPIEraseSector(uint16 sec);
+ * SpiFlashOpResult SPIEraseSector(uint16 sec);
* The 1st parameter is flash sector number.
+ * Note: Must disable cache read before using it.
- * SPIRead (Unsafe)
- * unknown SPIRead(uint32_t src_addr, uint32_t *des_addr, uint32_t size);
+ * SPIRead
+ * SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t *des_addr, uint32_t size);
* The 1st parameter is source addresses.
* The 2nd parameter is destination addresses.
* 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)
- * unknown SPIWrite(uint32_t des_addr, uint32_t *src_addr, uint32_t size);
+ * SPIWrite
+ * SpiFlashOpResult SPIWrite(uint32_t des_addr, uint32_t *src_addr, uint32_t size);
* The 1st parameter is destination addresses.
* The 2nd parameter is source addresses.
* 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
{
- uint8_t unknown0;
- uint8_t unknown1;
+ uint8_t header_magic;
+ uint8_t segment_count;
enum
{
MODE_QIO = 0,
@@ -56,20 +83,31 @@ typedef struct
SIZE_64MBIT = 5,
SIZE_128MBIT = 6,
} size : 4;
+ uint32_t entry_point;
+ uint32_t memory_offset;
+ uint32_t segment_size;
} ICACHE_STORE_TYPEDEF_ATTR SPIFlashInfo;
-SPIFlashInfo flash_get_info(void);
-uint8_t flash_get_size(void);
-uint32_t flash_get_size_byte(void);
-bool flash_set_size(uint8_t);
-bool flash_set_size_byte(uint32_t);
-uint16_t flash_get_sec_num(void);
-uint8_t flash_get_mode(void);
-uint32_t flash_get_speed(void);
+uint32_t flash_detect_size_byte(void);
+uint32_t flash_safe_get_size_byte(void);
+uint16_t flash_safe_get_sec_num(void);
+SpiFlashOpResult flash_safe_read(uint32 src_addr, uint32 *des_addr, uint32 size);
+SpiFlashOpResult flash_safe_write(uint32 des_addr, uint32 *src_addr, uint32 size);
+SpiFlashOpResult flash_safe_erase_sector(uint16 sec);
+SPIFlashInfo flash_rom_getinfo(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_default(void);
bool flash_init_data_blank(void);
bool flash_self_destruct(void);
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__
diff --git a/app/user/user_main.c b/app/user/user_main.c
index 7d470e2c..dee11754 100644
--- a/app/user/user_main.c
+++ b/app/user/user_main.c
@@ -60,7 +60,19 @@ void nodemcu_init(void)
NODE_DBG("Can not init platform for modules.\n");
return;
}
-
+
+#if defined(FLASH_SAFE_API)
+ if( flash_safe_get_size_byte() != flash_rom_get_size_byte()) {
+ NODE_ERR("Self adjust flash size.\n");
+ // Fit hardware real flash size.
+ flash_rom_set_size_byte(flash_safe_get_size_byte());
+ // Flash init data at FLASHSIZE - 0x04000 Byte.
+ flash_init_data_default();
+ // Flash blank data at FLASHSIZE - 0x02000 Byte.
+ flash_init_data_blank();
+ }
+#endif // defined(FLASH_SAFE_API)
+
if( !flash_init_data_written() ){
NODE_ERR("Restore init data.\n");
// Flash init data at FLASHSIZE - 0x04000 Byte.
diff --git a/examples/fragment.lua b/examples/fragment.lua
index c1cc4fb7..a56e423a 100644
--- a/examples/fragment.lua
+++ b/examples/fragment.lua
@@ -355,8 +355,11 @@ cs:listen(5683)
myvar=1
cs:var("myvar") -- get coap://192.168.18.103:5683/v1/v/myvar will return the value of myvar: 1
-function myfun()
+-- function should tack one string, return one string.
+function myfun(payload)
print("myfun called")
+ respond = "hello"
+ return respond
end
cs:func("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun
diff --git a/lua_modules/ds18b20/ds18b20.lua b/lua_modules/ds18b20/ds18b20.lua
index c31addcf..138c10da 100644
--- a/lua_modules/ds18b20/ds18b20.lua
+++ b/lua_modules/ds18b20/ds18b20.lua
@@ -3,6 +3,7 @@
-- NODEMCU TEAM
-- LICENCE: http://opensource.org/licenses/MIT
-- Vowstar
+-- 2015/02/14 sza2 Fix for negative values
--------------------------------------------------------------------------------
-- Set module name as parameter of require
@@ -96,12 +97,16 @@ function readNumber(addr, unit)
crc = ow.crc8(string.sub(data,1,8))
-- print("CRC="..crc)
if (crc == data:byte(9)) then
+ t = (data:byte(1) + data:byte(2) * 256)
+ if (t > 32767) then
+ t = t - 65536
+ end
if(unit == nil or unit == C) then
- t = (data:byte(1) + data:byte(2) * 256) * 625
+ t = t * 625
elseif(unit == F) then
- t = (data:byte(1) + data:byte(2) * 256) * 1125 + 320000
+ t = t * 1125 + 320000
elseif(unit == K) then
- t = (data:byte(1) + data:byte(2) * 256) * 625 + 2731500
+ t = t * 625 + 2731500
else
return nil
end