Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
AllAboutEE 2015-03-16 04:22:07 -05:00
commit eef53a532f
22 changed files with 565 additions and 268 deletions

View File

@ -1,6 +1,7 @@
# **NodeMCU** # # **NodeMCU** #
version 0.9.5 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) [![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 ###A lua based firmware for wifi-soc esp8266
@ -33,6 +34,10 @@ Tencent QQ group: 309957875<br />
- cross compiler (done) - cross compiler (done)
# Change log # Change log
2015-03-15<br />
bugs fixed: #239, #273.<br />
reduce coap module memory usage, add coap module to default built.
2015-03-11<br /> 2015-03-11<br />
fix bugs of spiffs.<br /> fix bugs of spiffs.<br />
build both float and integer version [latest releases](https://github.com/nodemcu/nodemcu-firmware/releases/latest).<br /> build both float and integer version [latest releases](https://github.com/nodemcu/nodemcu-firmware/releases/latest).<br />
@ -413,3 +418,25 @@ They'll be available as `u8g.<font_name>` in Lua.
-- first LED green, second LED white -- first LED green, second LED white
ws2812.writergb(4, string.char(0, 255, 0, 255, 255, 255)) 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")
```

View File

@ -76,7 +76,7 @@ int coap_parseToken(coap_buffer_t *tokbuf, const coap_header_t *hdr, const uint8
else else
if (hdr->tkl <= 8) if (hdr->tkl <= 8)
{ {
if (4 + hdr->tkl > buflen) if (4U + hdr->tkl > buflen)
return COAP_ERR_TOKEN_TOO_SHORT; // tok bigger than packet return COAP_ERR_TOKEN_TOO_SHORT; // tok bigger than packet
tokbuf->p = buf+4; // past header tokbuf->p = buf+4; // past header
tokbuf->len = hdr->tkl; tokbuf->len = hdr->tkl;
@ -93,7 +93,7 @@ int coap_buildToken(const coap_buffer_t *tokbuf, const coap_header_t *hdr, uint8
{ {
// inject token // inject token
uint8_t *p; uint8_t *p;
if (buflen < 4 + hdr->tkl) if (buflen < (4U + hdr->tkl))
return COAP_ERR_BUFFER_TOO_SMALL; return COAP_ERR_BUFFER_TOO_SMALL;
p = buf + 4; p = buf + 4;
if ((hdr->tkl > 0) && (hdr->tkl != tokbuf->len)) 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) if (hdr->tkl > 0)
c_memcpy(p, tokbuf->p, hdr->tkl); 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 // inject options
return hdr->tkl; 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) int coap_parseOption(coap_option_t *option, uint16_t *running_delta, const uint8_t **buf, size_t buflen)
{ {
const uint8_t *p = *buf; const uint8_t *p = *buf;
uint16_t len, delta;
uint8_t headlen = 1; uint8_t headlen = 1;
uint16_t len, delta;
if (buflen < headlen) // too small if (buflen < headlen) // too small
return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER; 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; 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) 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; size_t optionIndex = 0;
uint16_t delta = 0;
const uint8_t *p = buf + 4 + hdr->tkl; const uint8_t *p = buf + 4 + hdr->tkl;
const uint8_t *end = buf + buflen; const uint8_t *end = buf + buflen;
int rc; int rc;
uint16_t delta = 0;
if (p > end) if (p > end)
return COAP_ERR_OPTION_OVERRUNS_PACKET; // out of bounds 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; 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; int n = 0;
uint8_t *p = buf; 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 // 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 // FIXME, options is always sorted, can find faster than this
size_t i; 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; uint16_t optDelta = 0;
int rc = 0; int rc = 0;
if (p-buf > *buflen) if (((size_t)(p-buf)) > *buflen)
return COAP_ERR_BUFFER_TOO_SMALL; return COAP_ERR_BUFFER_TOO_SMALL;
optDelta = pkt->opts[i].num - running_delta; 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; 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) if (value<13)
{ {
*nibble = (0xFF & value); *nibble = (0xFF & value);
} }
else else
if (((uint32_t)value)<=0xFF+13) if (value<=0xFF+13)
{ {
*nibble = 13; *nibble = 13;
} else if (((uint32_t)value) -269 <=0xFFFF) } else if (value<=0xFFFF+269)
{ {
*nibble = 14; *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.code = rspcode;
pkt->hdr.id[0] = msgid_hi; pkt->hdr.id[0] = msgid_hi;
pkt->hdr.id[1] = msgid_lo; pkt->hdr.id[1] = msgid_lo;
pkt->numopts = 0; pkt->numopts = 1;
// need token in response // need token in response
if (tok) { if (tok) {
@ -442,7 +442,7 @@ unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val) {
return n; 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 }; coap_buffer_t the_token = { _token_data, 4 };
static unsigned short message_id; static unsigned short message_id;

View File

@ -18,13 +18,15 @@ extern "C" {
#define COAP_RESPONSE_CLASS(C) (((C) >> 5) & 0xFF) #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 typedef struct
{ {
uint8_t ver; uint8_t ver; /* CoAP version number */
uint8_t t; uint8_t t; /* CoAP Message Type */
uint8_t tkl; uint8_t tkl; /* Token length: indicates length of the Token field */
uint8_t code; 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]; uint8_t id[2];
} coap_header_t; } coap_header_t;
@ -42,23 +44,24 @@ typedef struct
typedef struct typedef struct
{ {
uint8_t num; uint8_t num; /* Option number. See http://tools.ietf.org/html/rfc7252#section-5.10 */
coap_buffer_t buf; coap_buffer_t buf; /* Option value */
} coap_option_t; } coap_option_t;
typedef struct typedef struct
{ {
coap_header_t hdr; coap_header_t hdr; /* Header of the packet */
coap_buffer_t tok; coap_buffer_t tok; /* Token value, size as specified by hdr.tkl */
uint8_t numopts; uint8_t numopts; /* Number of options */
coap_option_t opts[MAXOPT]; coap_option_t opts[MAXOPT]; /* Options of the packet. For possible entries see
coap_buffer_t payload; * http://tools.ietf.org/html/rfc7252#section-5.10 */
coap_rw_buffer_t scratch; // scratch->p = malloc(...) , and free it when done. 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; } 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 typedef enum
{ {
COAP_OPTION_IF_MATCH = 1, COAP_OPTION_IF_MATCH = 1,
@ -78,7 +81,7 @@ typedef enum
COAP_OPTION_PROXY_SCHEME = 39 COAP_OPTION_PROXY_SCHEME = 39
} coap_option_num_t; } 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 typedef enum
{ {
COAP_METHOD_GET = 1, COAP_METHOD_GET = 1,
@ -87,7 +90,7 @@ typedef enum
COAP_METHOD_DELETE = 4 COAP_METHOD_DELETE = 4
} coap_method_t; } 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 typedef enum
{ {
COAP_TYPE_CON = 0, COAP_TYPE_CON = 0,
@ -96,8 +99,8 @@ typedef enum
COAP_TYPE_RESET = 3 COAP_TYPE_RESET = 3
} coap_msgtype_t; } coap_msgtype_t;
//http://tools.ietf.org/html/draft-ietf-core-coap-18#section-5.2 //http://tools.ietf.org/html/rfc7252#section-5.2
//http://tools.ietf.org/html/draft-ietf-core-coap-18#section-12.1.2 //http://tools.ietf.org/html/rfc7252#section-12.1.2
#define MAKE_RSPCODE(clas, det) ((clas << 5) | (det)) #define MAKE_RSPCODE(clas, det) ((clas << 5) | (det))
typedef enum typedef enum
{ {
@ -107,7 +110,7 @@ typedef enum
COAP_RSPCODE_CHANGED = MAKE_RSPCODE(2, 4) COAP_RSPCODE_CHANGED = MAKE_RSPCODE(2, 4)
} coap_responsecode_t; } 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 typedef enum
{ {
COAP_CONTENTTYPE_NONE = -1, // bodge to allow us not to send option block 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; coap_luser_entry *next;
}; };
struct coap_endpoint_t struct coap_endpoint_t{
{ coap_method_t method; /* (i.e. POST, PUT or GET) */
coap_method_t method; coap_endpoint_func handler; /* callback function which handles this
coap_endpoint_func handler; * type of endpoint (and calls
const coap_endpoint_path_t *path; * coap_make_response() at some point) */
const char *core_attr; const coap_endpoint_path_t *path; /* path towards a resource (i.e. foo/bar/) */
coap_luser_entry *user_entry; 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); void coap_dumpPacket(coap_packet_t *pkt);
int coap_parse(coap_packet_t *pkt, const uint8_t *buf, size_t buflen); 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); 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_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); 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 coap_setup(void);
void endpoint_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 #ifdef __cplusplus
} }

View File

@ -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"); NODE_DBG("coap_client_response_handler is called.\n");
coap_packet_t pkt; coap_packet_t pkt;
pkt.content.p = NULL;
pkt.content.len = 0;
int rc; int rc;
if (0 != (rc = coap_parse(&pkt, data, len))){ if (0 != (rc = coap_parse(&pkt, data, len))){

View File

@ -1,11 +1,11 @@
#ifndef _COAP_SERVER_H #ifndef _COAP_CLIENT_H
#define _COAP_SERVER_H 1 #define _COAP_CLIENT_H 1
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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 #ifdef __cplusplus
} }

View File

@ -1,53 +1,60 @@
#include "user_config.h" #include "user_config.h"
#include "c_types.h" #include "c_types.h"
#include "c_stdlib.h"
#include "coap.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"); NODE_DBG("coap_server_respond is called.\n");
if(len>size){ size_t rlen = rsplen;
NODE_DBG("len:%d, size:%d\n",len,size);
return 0;
}
size_t rsplen = size;
coap_packet_t pkt; coap_packet_t pkt;
pkt.content.p = NULL;
pkt.content.len = 0;
uint8_t scratch_raw[4]; uint8_t scratch_raw[4];
coap_rw_buffer_t scratch_buf = {scratch_raw, sizeof(scratch_raw)}; coap_rw_buffer_t scratch_buf = {scratch_raw, sizeof(scratch_raw)};
int rc; int rc;
#ifdef COAP_DEBUG #ifdef COAP_DEBUG
NODE_DBG("Received: "); NODE_DBG("Received: ");
coap_dump(data, len, true); coap_dump(req, reqlen, true);
NODE_DBG("\n"); NODE_DBG("\n");
#endif #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); NODE_DBG("Bad packet rc=%d\n", rc);
return 0; return 0;
} }
else else
{ {
coap_packet_t rsppkt; coap_packet_t rsppkt;
rsppkt.content.p = NULL;
rsppkt.content.len = 0;
#ifdef COAP_DEBUG #ifdef COAP_DEBUG
coap_dumpPacket(&pkt); coap_dumpPacket(&pkt);
#endif #endif
coap_handle_req(&scratch_buf, &pkt, &rsppkt); 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); NODE_DBG("coap_build failed rc=%d\n", rc);
return 0; // return 0;
rlen = 0;
} }
else else
{ {
#ifdef COAP_DEBUG #ifdef COAP_DEBUG
NODE_DBG("Responding: "); NODE_DBG("Responding: ");
coap_dump(data, rsplen, true); coap_dump(rsp, rlen, true);
NODE_DBG("\n"); NODE_DBG("\n");
#endif #endif
#ifdef COAP_DEBUG #ifdef COAP_DEBUG
coap_dumpPacket(&rsppkt); coap_dumpPacket(&rsppkt);
#endif #endif
} }
return rsplen; if(rsppkt.content.p){
c_free(rsppkt.content.p);
rsppkt.content.p = NULL;
rsppkt.content.len = 0;
}
return rlen;
} }
} }

View File

@ -5,7 +5,7 @@
extern "C" { extern "C" {
#endif #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 #ifdef __cplusplus
} }

View File

@ -1,5 +1,6 @@
#include "c_stdio.h" #include "c_stdio.h"
#include "c_string.h" #include "c_string.h"
#include "c_stdlib.h"
#include "coap.h" #include "coap.h"
#include "lua.h" #include "lua.h"
@ -8,20 +9,24 @@
#include "os_type.h" #include "os_type.h"
static char rsp[MAX_PAYLOAD_SIZE] = ""; void build_well_known_rsp(char *rsp, uint16_t rsplen);
const uint16_t rsplen = MAX_PAYLOAD_SIZE;
void build_well_known_rsp(void);
void endpoint_setup(void) void endpoint_setup(void)
{ {
coap_setup(); coap_setup();
build_well_known_rsp();
} }
static const coap_endpoint_path_t path_well_known_core = {2, {".well-known", "core"}}; 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) 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"}}; 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; const coap_option_t *opt;
uint8_t count; uint8_t count;
int n;
if (NULL != (opt = coap_findOptions(inpkt, COAP_OPTION_URI_PATH, &count))) 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] 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); 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)) if(c_strlen(h->name))
{ {
n = lua_gettop(h->L);
lua_getglobal(h->L, h->name); lua_getglobal(h->L, h->name);
if (!lua_isnumber(h->L, -1)) { if (!lua_isnumber(h->L, -1)) {
NODE_DBG ("should be a number.\n"); 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); return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
} else { } else {
const char *res = lua_tostring(h->L,-1); 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); 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; const coap_option_t *opt;
uint8_t count; uint8_t count;
int n;
if (NULL != (opt = coap_findOptions(inpkt, COAP_OPTION_URI_PATH, &count))) 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] 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)) if(c_strlen(h->name))
{ {
n = lua_gettop(h->L);
lua_getglobal(h->L, h->name); lua_getglobal(h->L, h->name);
if (lua_type(h->L, -1) != LUA_TFUNCTION) { if (lua_type(h->L, -1) != LUA_TFUNCTION) {
NODE_DBG ("should be a function\n"); 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); return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
} else { } 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 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; size_t len = 0;
const char *ret = luaL_checklstring( h->L, -1, &len ); const char *ret = luaL_checklstring( h->L, -1, &len );
if(len > MAX_PAYLOAD_SIZE){ if(len > MAX_PAYLOAD_SIZE){
lua_settop(h->L, n);
luaL_error( h->L, "return string:<MAX_PAYLOAD_SIZE" ); luaL_error( h->L, "return string:<MAX_PAYLOAD_SIZE" );
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE); return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
} }
NODE_DBG((char *)ret); NODE_DBG((char *)ret);
NODE_DBG("\n"); 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); return coap_make_response(scratch, outpkt, ret, len, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
} }
} else { } 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); 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} {(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; const coap_endpoint_t *ep = endpoints;
int i; int i;
uint16_t len = rsplen; uint16_t len = rsplen;
c_memset(rsp, 0, sizeof(rsp)); c_memset(rsp, 0, len);
len--; // Null-terminated string len--; // Null-terminated string

View File

@ -24,6 +24,8 @@ coap_pdu_t * coap_new_pdu(void) {
c_free(pdu); c_free(pdu);
return NULL; 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' pdu->msg.p = (uint8_t *)c_zalloc(MAX_REQUEST_SIZE+1); // +1 for string '\0'
if(!pdu->msg.p){ if(!pdu->msg.p){

View File

@ -10,6 +10,7 @@
// #define FLASH_8M // #define FLASH_8M
// #define FLASH_16M // #define FLASH_16M
#define FLASH_AUTOSIZE #define FLASH_AUTOSIZE
#define FLASH_SAFE_API
// #define DEVELOP_VERSION // #define DEVELOP_VERSION
#define FULL_VERSION_FOR_USER #define FULL_VERSION_FOR_USER

View File

@ -27,7 +27,7 @@
#define LUA_USE_MODULES_OW #define LUA_USE_MODULES_OW
#define LUA_USE_MODULES_BIT #define LUA_USE_MODULES_BIT
#define LUA_USE_MODULES_MQTT #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_U8G
#define LUA_USE_MODULES_WS2812 #define LUA_USE_MODULES_WS2812
#endif /* LUA_USE_MODULES */ #endif /* LUA_USE_MODULES */

View File

@ -7,6 +7,6 @@
#define NODE_VERSION_INTERNAL 0U #define NODE_VERSION_INTERNAL 0U
#define NODE_VERSION "NodeMCU 0.9.5" #define NODE_VERSION "NodeMCU 0.9.5"
#define BUILD_DATE "build 20150311" #define BUILD_DATE "build 20150315"
#endif /* __USER_VERSION_H__ */ #endif /* __USER_VERSION_H__ */

View File

@ -63,7 +63,7 @@ int c_stderr = 1001;
#define ENDIAN_LITTLE 1234 #define ENDIAN_LITTLE 1234
#define ENDIAN_BIG 4321 #define ENDIAN_BIG 4321
#define ENDIAN_PDP 3412 #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 $ */ /* $Id: strichr.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */

View File

@ -659,13 +659,19 @@ typedef struct LoadFSF {
static const char *getFSF (lua_State *L, void *ud, size_t *size) { static const char *getFSF (lua_State *L, void *ud, size_t *size) {
LoadFSF *lf = (LoadFSF *)ud; LoadFSF *lf = (LoadFSF *)ud;
(void)L; (void)L;
if (L == NULL && size == NULL) // Direct mode check
return NULL;
if (lf->extraline) { if (lf->extraline) {
lf->extraline = 0; lf->extraline = 0;
*size = 1; *size = 1;
return "\n"; return "\n";
} }
if (fs_eof(lf->f)) return NULL; if (fs_eof(lf->f)) return NULL;
*size = fs_read(lf->f, lf->buff, sizeof(lf->buff)); *size = fs_read(lf->f, lf->buff, sizeof(lf->buff));
return (*size > 0) ? lf->buff : NULL; return (*size > 0) ? lf->buff : NULL;
} }

View File

@ -37,20 +37,20 @@ static void coap_received(void *arg, char *pdata, unsigned short len)
struct espconn *pesp_conn = arg; struct espconn *pesp_conn = arg;
lcoap_userdata *cud = (lcoap_userdata *)pesp_conn->reverse; 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 c_memset(buf, 0, sizeof(buf)); // wipe prev data
if (len > MAX_MESSAGE_SIZE) { if (len > MAX_MESSAGE_SIZE) {
NODE_DBG("Request Entity Too Large.\n"); // NOTE: should response 4.13 to client... NODE_DBG("Request Entity Too Large.\n"); // NOTE: should response 4.13 to client...
return; 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); 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) 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; struct espconn *pesp_conn = arg;
coap_packet_t pkt; 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 c_memset(buf, 0, sizeof(buf)); // wipe prev data
static int n = 0;
int rc; int rc;
if ((len == 1460) && (1460 <= MAX_MESSAGE_SIZE)){ if( len > MAX_MESSAGE_SIZE )
c_memcpy(buf, pdata, len); // max length is 1460, another part of data is coming in next callback {
n = len; NODE_DBG("Request Entity Too Large.\n"); // NOTE: should response 4.13 to client...
return; 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))){ if (0 != (rc = coap_parse(&pkt, buf, len))){
NODE_DBG("Bad packet rc=%d\n", rc); 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) if(pesp_conn->proto.udp->remote_port || pesp_conn->proto.udp->local_port)
espconn_delete(pesp_conn); espconn_delete(pesp_conn);
} }
c_memset(buf, 0, sizeof(buf)); // c_memset(buf, 0, sizeof(buf));
n = 0;
} }
// Lua: client:request( [CON], uri, [payload] ) // 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 *variable_entry;
extern coap_luser_entry *function_entry; extern coap_luser_entry *function_entry;
extern void build_well_known_rsp(void);
// Lua: coap:var/func( string ) // Lua: coap:var/func( string )
static int coap_regist( lua_State* L, const char* mt, int isvar ) 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->L = L;
h->name = name; h->name = name;
build_well_known_rsp(); // rebuild .well-known
NODE_DBG("coap_regist is called.\n"); NODE_DBG("coap_regist is called.\n");
return 0; return 0;
} }

View File

@ -29,7 +29,7 @@
static int node_restart( lua_State* L ) static int node_restart( lua_State* L )
{ {
system_restart(); system_restart();
return 0; return 0;
} }
// Lua: dsleep( us, option ) // Lua: dsleep( us, option )
@ -56,7 +56,7 @@ static int node_deepsleep( lua_State* L )
else else
system_deep_sleep( us ); system_deep_sleep( us );
} }
return 0; return 0;
} }
// Lua: dsleep_set_options // Lua: dsleep_set_options
@ -80,10 +80,14 @@ 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
return 8; 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() // Lua: chipid()
@ -91,7 +95,7 @@ static int node_chipid( lua_State* L )
{ {
uint32_t id = system_get_chip_id(); uint32_t id = system_get_chip_id();
lua_pushinteger(L, id); lua_pushinteger(L, id);
return 1; return 1;
} }
// Lua: readvdd33() // Lua: readvdd33()
static int node_readvdd33( lua_State* L ) 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(); uint32_t id = spi_flash_get_id();
lua_pushinteger( L, id ); lua_pushinteger( L, id );
return 1; return 1;
} }
// 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;
} }
// Lua: heap() // Lua: heap()
@ -131,7 +134,7 @@ static int node_heap( lua_State* L )
{ {
uint32_t sz = system_get_free_heap_size(); uint32_t sz = system_get_free_heap_size();
lua_pushinteger(L, sz); lua_pushinteger(L, sz);
return 1; return 1;
} }
static lua_State *gL = NULL; static lua_State *gL = NULL;
@ -146,7 +149,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 {
@ -155,7 +158,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 {
@ -163,14 +166,14 @@ static int node_led( lua_State* L )
} }
led_high_count = (uint32_t)high / READLINE_INTERVAL; led_high_count = (uint32_t)high / READLINE_INTERVAL;
led_low_count = (uint32_t)low / READLINE_INTERVAL; led_low_count = (uint32_t)low / READLINE_INTERVAL;
return 0; return 0;
} }
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;
@ -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); // 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);
} }
// Lua: key(type, function) // Lua: key(type, function)
@ -213,32 +216,32 @@ static int node_key( lua_State* L )
{ {
int *ref = NULL; int *ref = NULL;
size_t sl; size_t sl;
const char *str = luaL_checklstring( L, 1, &sl ); const char *str = luaL_checklstring( L, 1, &sl );
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;
} }
return 0; return 0;
} }
#endif #endif
@ -248,15 +251,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
@ -271,18 +274,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);
} }
@ -296,15 +299,15 @@ 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;
return 0; return 0;
} }
@ -312,26 +315,26 @@ 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
} }
return 0; return 0;
} }
static int writer(lua_State* L, const void* p, size_t size, void* u) 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;
} }
@ -343,45 +346,45 @@ 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");
} }
@ -391,7 +394,7 @@ static int node_compile( lua_State* L )
// Module function map // Module function map
#define MIN_OPT_LEVEL 2 #define MIN_OPT_LEVEL 2
#include "lrodefs.h" #include "lrodefs.h"
const LUA_REG_TYPE node_map[] = const LUA_REG_TYPE node_map[] =
{ {
{ LSTRKEY( "restart" ), LFUNCVAL( node_restart ) }, { LSTRKEY( "restart" ), LFUNCVAL( node_restart ) },
{ LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) }, { LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) },
@ -408,7 +411,7 @@ 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) },
// 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

View File

@ -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 @@
// 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__

View File

@ -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 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; #define FLASH_BUFFER_SIZE_DETECT 32
spi_flash_info = *((SPIFlashInfo *)(FLASH_MAP_START_ADDRESS)); uint32_t dummy_size = FLASH_SIZE_256KBYTE;
// spi_flash_read(0, (uint32 *)(& spi_flash_info), sizeof(spi_flash_info)); uint8_t data_orig[FLASH_BUFFER_SIZE_DETECT] ICACHE_STORE_ATTR = {0};
return spi_flash_info; 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))
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)
{ {
case SIZE_2MBIT: dummy_size = FLASH_SIZE_256KBYTE;
// 2Mbit, 256kByte while ((dummy_size < FLASH_SIZE_16MBYTE) &&
flash_size = 256 * 1024; (SPI_FLASH_RESULT_OK == flash_safe_read(dummy_size, (uint32 *)data_new, FLASH_BUFFER_SIZE_DETECT)) &&
break; (0 != os_memcmp(data_orig, data_new, FLASH_BUFFER_SIZE_DETECT))
case SIZE_4MBIT: )
// 4Mbit, 512kByte {
flash_size = 512 * 1024; dummy_size *= 2;
break; }
case SIZE_8MBIT: };
// 8Mbit, 1MByte return dummy_size;
flash_size = 1 * 1024 * 1024; #undef FLASH_BUFFER_SIZE_DETECT
break; }
case SIZE_16MBIT:
// 16Mbit, 2MByte uint32_t flash_safe_get_size_byte(void)
flash_size = 2 * 1024 * 1024; {
break; static uint32_t flash_size = 0;
case SIZE_32MBIT: if (flash_size == 0)
// 32Mbit, 4MByte {
flash_size = 4 * 1024 * 1024; flash_size = flash_detect_size_byte();
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; 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!!!!! // 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!!!
@ -102,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.
@ -132,22 +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)
{ {
//static uint16_t sec_num = 0; //static uint16_t sec_num = 0;
// return flash_get_size_byte() / (SPI_FLASH_SEC_SIZE); // return flash_rom_get_size_byte() / (SPI_FLASH_SEC_SIZE);
// c_printf("\nflash_get_size_byte()=%d\n", ( flash_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 ) // if( sec_num == 0 )
//{ //{
// sec_num = 4 * 1024 * 1024 / (SPI_FLASH_SEC_SIZE); // sec_num = 4 * 1024 * 1024 / (SPI_FLASH_SEC_SIZE);
//} //}
//return sec_num; //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) switch (spi_flash_info.mode)
{ {
// Reserved for future use // Reserved for future use
@ -163,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:
@ -189,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)
{ {
@ -210,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;
} }
@ -227,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;
} }
@ -254,3 +400,28 @@ uint8_t byte_of_aligned_array(const uint8_t *aligned_array, uint32_t index)
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;
// }

View File

@ -4,34 +4,61 @@
#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,
@ -56,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__

View File

@ -60,7 +60,19 @@ void nodemcu_init(void)
NODE_DBG("Can not init platform for modules.\n"); NODE_DBG("Can not init platform for modules.\n");
return; 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() ){ if( !flash_init_data_written() ){
NODE_ERR("Restore init data.\n"); NODE_ERR("Restore init data.\n");
// Flash init data at FLASHSIZE - 0x04000 Byte. // Flash init data at FLASHSIZE - 0x04000 Byte.

View File

@ -355,8 +355,11 @@ cs:listen(5683)
myvar=1 myvar=1
cs:var("myvar") -- get coap://192.168.18.103:5683/v1/v/myvar will return the value of 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") print("myfun called")
respond = "hello"
return respond
end end
cs:func("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun cs:func("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun

View File

@ -3,6 +3,7 @@
-- NODEMCU TEAM -- NODEMCU TEAM
-- LICENCE: http://opensource.org/licenses/MIT -- LICENCE: http://opensource.org/licenses/MIT
-- Vowstar <vowstar@nodemcu.com> -- Vowstar <vowstar@nodemcu.com>
-- 2015/02/14 sza2 <sza2trash@gmail.com> Fix for negative values
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Set module name as parameter of require -- Set module name as parameter of require
@ -96,12 +97,16 @@ function readNumber(addr, unit)
crc = ow.crc8(string.sub(data,1,8)) crc = ow.crc8(string.sub(data,1,8))
-- print("CRC="..crc) -- print("CRC="..crc)
if (crc == data:byte(9)) then 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 if(unit == nil or unit == C) then
t = (data:byte(1) + data:byte(2) * 256) * 625 t = t * 625
elseif(unit == F) then elseif(unit == F) then
t = (data:byte(1) + data:byte(2) * 256) * 1125 + 320000 t = t * 1125 + 320000
elseif(unit == K) then elseif(unit == K) then
t = (data:byte(1) + data:byte(2) * 256) * 625 + 2731500 t = t * 625 + 2731500
else else
return nil return nil
end end