Johny Mattsson 526d21dab4 Major cleanup - c_whatever is finally history. (#2838)
The PR removed the bulk of non-newlib headers from the NodeMCU source base.  
app/libc has now been cut down to the bare minimum overrides to shadow the 
corresponding functions in the SDK's libc. The old c_xyz.h headerfiles have been 
nuked in favour of the standard <xyz.h> headers, with a few exceptions over in 
sdk-overrides. Again, shipping a libc.a without headers is a terrible thing to do. We're 
still living on a prayer that libc was configured the same was as a default-configured
xtensa gcc toolchain assumes it is. That part I cannot do anything about, unfortunately, 
but it's no worse than it has been before.

This enables our source files to compile successfully using the standard header files, 
and use the typical malloc()/calloc()/realloc()/free(), the strwhatever()s and 
memwhatever()s. These end up, through macro and linker magic, mapped to the 
appropriate SDK or ROM functions.
2019-07-22 00:58:21 +03:00

811 lines
23 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Module for interfacing with system
#include "module.h"
#include "lauxlib.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "legc.h"
#include "lopcodes.h"
#include "lstring.h"
#include "lundump.h"
#include "platform.h"
#include "lflash.h"
#include "c_types.h"
#include <string.h>
#include "driver/uart.h"
#include "user_interface.h"
#include "flash_api.h"
#include "vfs.h"
#include "user_version.h"
#include "rom.h"
#include "task/task.h"
#define CPU80MHZ 80
#define CPU160MHZ 160
// Lua: restart()
static int node_restart( lua_State* L )
{
system_restart();
return 0;
}
static int dsleepMax( lua_State *L ) {
lua_pushnumber(L, (uint64_t)system_rtc_clock_cali_proc()*(0x80000000-1)/(0x1000));
return 1;
}
// Lua: dsleep( us, option )
static int node_deepsleep( lua_State* L )
{
uint64 us;
uint8 option;
//us = luaL_checkinteger( L, 1 );
// Set deleep option, skip if nil
if ( lua_isnumber(L, 2) )
{
option = lua_tointeger(L, 2);
if ( option < 0 || option > 4)
return luaL_error( L, "wrong arg range" );
else
system_deep_sleep_set_option( option );
}
bool instant = false;
if (lua_isnumber(L, 3))
instant = lua_tointeger(L, 3);
// Set deleep time, skip if nil
if ( lua_isnumber(L, 1) )
{
us = luaL_checknumber(L, 1);
// if ( us <= 0 )
if ( us < 0 )
return luaL_error( L, "wrong arg range" );
else
{
if (instant)
system_deep_sleep_instant(us);
else
system_deep_sleep( us );
}
}
return 0;
}
#ifdef PMSLEEP_ENABLE
#include "pm/pmSleep.h"
int node_sleep_resume_cb_ref= LUA_NOREF;
void node_sleep_resume_cb(void)
{
PMSLEEP_DBG("START");
pmSleep_execute_lua_cb(&node_sleep_resume_cb_ref);
PMSLEEP_DBG("END");
}
// Lua: node.sleep(table)
static int node_sleep( lua_State* L )
{
#ifdef TIMER_SUSPEND_ENABLE
pmSleep_INIT_CFG(cfg);
cfg.sleep_mode=LIGHT_SLEEP_T;
if(lua_istable(L, 1)){
pmSleep_parse_table_lua(L, 1, &cfg, NULL, &node_sleep_resume_cb_ref);
}
else{
return luaL_argerror(L, 1, "must be table");
}
cfg.resume_cb_ptr = &node_sleep_resume_cb;
pmSleep_suspend(&cfg);
#else
dbg_printf("\n The option \"TIMER_SUSPEND_ENABLE\" in \"app/include/user_config.h\" was disabled during FW build!\n");
return luaL_error(L, "node.sleep() is unavailable");
#endif
return 0;
}
#else
static int node_sleep( lua_State* L )
{
dbg_printf("\n The options \"TIMER_SUSPEND_ENABLE\" and \"PMSLEEP_ENABLE\" in \"app/include/user_config.h\" were disabled during FW build!\n");
return luaL_error(L, "node.sleep() is unavailable");
}
#endif //PMSLEEP_ENABLE
static int node_info( lua_State* L )
{
lua_pushinteger(L, NODE_VERSION_MAJOR);
lua_pushinteger(L, NODE_VERSION_MINOR);
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_rom_get_size_byte() / 1024); // flash size in KB
lua_pushinteger(L, flash_rom_get_mode());
lua_pushinteger(L, flash_rom_get_speed());
return 8;
}
// Lua: chipid()
static int node_chipid( lua_State* L )
{
uint32_t id = system_get_chip_id();
lua_pushinteger(L, id);
return 1;
}
// deprecated, moved to adc module
// Lua: readvdd33()
// static int node_readvdd33( lua_State* L )
// {
// uint32_t vdd33 = readvdd33();
// lua_pushinteger(L, vdd33);
// return 1;
// }
// Lua: flashid()
static int node_flashid( lua_State* L )
{
uint32_t id = spi_flash_get_id();
lua_pushinteger( L, id );
return 1;
}
// Lua: flashsize()
static int node_flashsize( lua_State* L )
{
uint32_t sz = flash_rom_get_size_byte();
lua_pushinteger( L, sz );
return 1;
}
// Lua: heap()
static int node_heap( lua_State* L )
{
uint32_t sz = system_get_free_heap_size();
lua_pushinteger(L, sz);
return 1;
}
extern int lua_put_line(const char *s, size_t l);
extern bool user_process_input(bool force);
// Lua: input("string")
static int node_input( lua_State* L ) {
size_t l = 0;
const char *s = luaL_checklstring(L, 1, &l);
if (lua_put_line(s, l)) {
NODE_DBG("Result (if any):\n");
user_process_input(true);
}
return 0;
}
static int output_redir_ref = LUA_NOREF;
static int serial_debug = 1;
void output_redirect(const char *str) {
lua_State *L = lua_getstate();
// if(strlen(str)>=TX_BUFF_SIZE){
// NODE_ERR("output too long.\n");
// return;
// }
if (output_redir_ref == LUA_NOREF) {
uart0_sendStr(str);
return;
}
if (serial_debug != 0) {
uart0_sendStr(str);
}
lua_rawgeti(L, LUA_REGISTRYINDEX, output_redir_ref);
lua_pushstring(L, str);
lua_call(L, 1, 0); // this call back function should never user output.
}
// Lua: output(function(c), debug)
static int node_output( lua_State* L )
{
// luaL_checkanyfunction(L, 1);
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)
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)
luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref);
output_redir_ref = LUA_NOREF;
serial_debug = 1;
return 0;
}
if ( lua_isnumber(L, 2) )
{
serial_debug = lua_tointeger(L, 2);
if (serial_debug != 0)
serial_debug = 1;
} else {
serial_debug = 1; // default to 1
}
return 0;
}
static int writer(lua_State* L, const void* p, size_t size, void* u)
{
UNUSED(L);
int file_fd = *( (int *)u );
if (!file_fd)
return 1;
NODE_DBG("get fd:%d,size:%d\n", file_fd, size);
if (size != 0 && (size != vfs_write(file_fd, (const char *)p, size)) )
return 1;
NODE_DBG("write fd:%d,size:%d\n", file_fd, size);
return 0;
}
#define toproto(L,i) (clvalue(L->top+(i))->l.p)
// Lua: compile(filename) -- compile lua file into lua bytecode, and save to .lc
static int node_compile( lua_State* L )
{
Proto* f;
int file_fd = 0;
size_t len;
const char *fname = luaL_checklstring( L, 1, &len );
const char *basename = vfs_basename( fname );
luaL_argcheck(L, strlen(basename) <= FS_OBJ_NAME_LEN && strlen(fname) == len, 1, "filename invalid");
char *output = luaM_malloc( L, len+1 );
strcpy(output, fname);
// check here that filename end with ".lua".
if (len < 4 || (strcmp( output + len - 4, ".lua") != 0) ) {
luaM_free( L, output );
return luaL_error(L, "not a .lua file");
}
output[strlen(output) - 2] = 'c';
output[strlen(output) - 1] = '\0';
NODE_DBG(output);
NODE_DBG("\n");
if (luaL_loadfsfile(L, fname) != 0) {
luaM_free( L, output );
return luaL_error(L, lua_tostring(L, -1));
}
f = toproto(L, -1);
int stripping = 1; /* strip debug information? */
file_fd = vfs_open(output, "w+");
if (!file_fd)
{
luaM_free( L, output );
return luaL_error(L, "cannot open/write to file");
}
lua_lock(L);
int result = luaU_dump(L, f, writer, &file_fd, stripping);
lua_unlock(L);
if (vfs_flush(file_fd) != VFS_RES_OK) {
// overwrite Lua error, like writer() does in case of a file io error
result = 1;
}
vfs_close(file_fd);
file_fd = 0;
luaM_free( L, output );
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) {
return luaL_error(L, "target lua_Number is integral but fractional value found");
}
if (result == 1) { // result status generated by writer() or fs_flush() fail
return luaL_error(L, "writing to file failed");
}
return 0;
}
// Task callback handler for node.task.post()
static task_handle_t do_node_task_handle;
static void do_node_task (task_param_t task_fn_ref, uint8_t prio)
{
lua_State* L = lua_getstate();
lua_rawgeti(L, LUA_REGISTRYINDEX, (int)task_fn_ref);
luaL_unref(L, LUA_REGISTRYINDEX, (int)task_fn_ref);
lua_pushinteger(L, prio);
lua_call(L, 1, 0);
}
// Lua: node.task.post([priority],task_cb) -- schedule a task for execution next
static int node_task_post( lua_State* L )
{
int n = 1, Ltype = lua_type(L, 1);
unsigned priority = TASK_PRIORITY_MEDIUM;
if (Ltype == LUA_TNUMBER) {
priority = (unsigned) luaL_checkint(L, 1);
luaL_argcheck(L, priority <= TASK_PRIORITY_HIGH, 1, "invalid priority");
Ltype = lua_type(L, ++n);
}
luaL_argcheck(L, Ltype == LUA_TFUNCTION || Ltype == LUA_TLIGHTFUNCTION, n, "invalid function");
lua_pushvalue(L, n);
int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX);
if (!do_node_task_handle) // bind the task handle to do_node_task on 1st call
do_node_task_handle = task_get_id(do_node_task);
if(!task_post(priority, do_node_task_handle, (task_param_t)task_fn_ref)) {
luaL_unref(L, LUA_REGISTRYINDEX, task_fn_ref);
luaL_error(L, "Task queue overflow. Task not posted");
}
return 0;
}
// Lua: setcpufreq(mhz)
// mhz is either CPU80MHZ od CPU160MHZ
static int node_setcpufreq(lua_State* L)
{
// http://www.esp8266.com/viewtopic.php?f=21&t=1369
uint32_t new_freq = luaL_checkinteger(L, 1);
if (new_freq == CPU160MHZ){
REG_SET_BIT(0x3ff00014, BIT(0));
ets_update_cpu_frequency(CPU160MHZ);
} else {
REG_CLR_BIT(0x3ff00014, BIT(0));
ets_update_cpu_frequency(CPU80MHZ);
}
new_freq = ets_get_cpu_frequency();
lua_pushinteger(L, new_freq);
return 1;
}
// Lua: freq = node.getcpufreq()
static int node_getcpufreq(lua_State* L)
{
lua_pushinteger(L, system_get_cpu_freq());
return 1;
}
// Lua: code, reason [, exccause, epc1, epc2, epc3, excvaddr, depc ] = bootreason()
static int node_bootreason (lua_State *L)
{
const struct rst_info *ri = system_get_rst_info ();
uint32_t arr[8] = {
rtc_get_reset_reason(),
ri->reason,
ri->exccause, ri->epc1, ri->epc2, ri->epc3, ri->excvaddr, ri->depc
};
int i, n = ((ri->reason != REASON_EXCEPTION_RST) ? 2 : 8);
for (i = 0; i < n; ++i)
lua_pushinteger (L, arr[i]);
return n;
}
// Lua: restore()
static int node_restore (lua_State *L)
{
system_restore();
return 0;
}
#ifdef LUA_OPTIMIZE_DEBUG
/* node.stripdebug([level[, function]]). 
* level: 1 don't discard debug
* 2 discard Local and Upvalue debug info
* 3 discard Local, Upvalue and lineno debug info.
* function: Function to be stripped as per setfenv except 0 not permitted.
* If no arguments then the current default setting is returned.
* If function is omitted, this is the default setting for future compiles
* The function returns an estimated integer count of the bytes stripped.
*/
static int node_stripdebug (lua_State *L) {
int level;
if (L->top == L->base) {
lua_pushlightuserdata(L, &luaG_stripdebug );
lua_gettable(L, LUA_REGISTRYINDEX);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushinteger(L, LUA_OPTIMIZE_DEBUG);
}
return 1;
}
level = luaL_checkint(L, 1);
if ((level <= 0) || (level > 3)) luaL_argerror(L, 1, "must in range 1-3");
if (L->top == L->base + 1) {
/* Store the default level in the registry if no function parameter */
lua_pushlightuserdata(L, &luaG_stripdebug);
lua_pushinteger(L, level);
lua_settable(L, LUA_REGISTRYINDEX);
lua_settop(L,0);
return 0;
}
if (level == 1) {
lua_settop(L,0);
lua_pushinteger(L, 0);
return 1;
}
if (!lua_isfunction(L, 2)) {
int scope = luaL_checkint(L, 2);
if (scope > 0) {
/* if the function parameter is a +ve integer then climb to find function */
lua_Debug ar;
lua_pop(L, 1); /* pop level as getinfo will replace it by the function */
if (lua_getstack(L, scope, &ar)) {
lua_getinfo(L, "f", &ar);
}
}
}
if(!lua_isfunction(L, 2) || lua_iscfunction(L, -1)) luaL_argerror(L, 2, "must be a Lua Function");
// lua_lock(L);
Proto *f = clvalue(L->base + 1)->l.p;
// lua_unlock(L);
lua_settop(L,0);
lua_pushinteger(L, luaG_stripdebug(L, f, level, 1));
return 1;
}
#endif
// Lua: node.egc.setmode( mode, [param])
// where the mode is one of the node.egc constants NOT_ACTIVE , ON_ALLOC_FAILURE,
// ON_MEM_LIMIT, ALWAYS. In the case of ON_MEM_LIMIT an integer parameter is reqired
// See legc.h and lecg.c.
static int node_egc_setmode(lua_State* L) {
unsigned mode = luaL_checkinteger(L, 1);
int limit = luaL_optinteger (L, 2, 0);
luaL_argcheck(L, mode <= (EGC_ON_ALLOC_FAILURE | EGC_ON_MEM_LIMIT | EGC_ALWAYS), 1, "invalid mode");
luaL_argcheck(L, !(mode & EGC_ON_MEM_LIMIT) || limit!=0, 1, "limit must be non-zero");
legc_set_mode( L, mode, limit );
return 0;
}
// totalallocated, estimatedused = node.egc.meminfo()
static int node_egc_meminfo(lua_State *L) {
global_State *g = G(L);
lua_pushinteger(L, g->totalbytes);
lua_pushinteger(L, g->estimate);
return 2;
}
//
// Lua: osprint(true/false)
// Allows you to turn on the native Espressif SDK printing
static int node_osprint( lua_State* L )
{
if (lua_toboolean(L, 1)) {
system_set_os_print(1);
} else {
system_set_os_print(0);
}
return 0;
}
int node_random_range(int l, int u) {
// The range is the number of different values to return
unsigned int range = u + 1 - l;
// If this is very large then use simpler code
if (range >= 0x7fffffff) {
unsigned int v;
// This cannot loop more than half the time
while ((v = os_random()) >= range) {
}
// Now v is in the range [0, range)
return v + l;
}
// Easy case, with only one value, we know the result
if (range == 1) {
return l;
}
// Another easy case -- uniform 32-bit
if (range == 0) {
return os_random();
}
// Now we have to figure out what a large multiple of range is
// that just fits into 32 bits.
// The limit will be less than 1 << 32 by some amount (not much)
uint32_t limit = ((0x80000000 / ((range + 1) >> 1)) - 1) * range;
uint32_t v;
while ((v = os_random()) >= limit) {
}
// Now v is uniformly distributed in [0, limit) and limit is a multiple of range
return (v % range) + l;
}
static int node_random (lua_State *L) {
int u;
int l;
switch (lua_gettop(L)) { /* check number of arguments */
case 0: { /* no arguments */
#ifdef LUA_NUMBER_INTEGRAL
lua_pushnumber(L, 0); /* Number between 0 and 1 - always 0 with ints */
#else
lua_pushnumber(L, (lua_Number)os_random() / (lua_Number)(1LL << 32));
#endif
return 1;
}
case 1: { /* only upper limit */
l = 1;
u = luaL_checkint(L, 1);
break;
}
case 2: { /* lower and upper limits */
l = luaL_checkint(L, 1);
u = luaL_checkint(L, 2);
break;
}
default:
return luaL_error(L, "wrong number of arguments");
}
luaL_argcheck(L, l<=u, 2, "interval is empty");
lua_pushnumber(L, node_random_range(l, u)); /* int between `l' and `u' */
return 1;
}
#ifdef DEVELOPMENT_TOOLS
// Lua: rec = node.readrcr(id)
static int node_readrcr (lua_State *L) {
int id = luaL_checkinteger(L, 1);
char *data;
int n = platform_rcr_read(id, (void **)&data);
if (n == ~0) return 0;
lua_pushlstring(L, data, n);
return 1;
}
// Lua: n = node.writercr(id,rec)
static int node_writercr (lua_State *L) {
int id = luaL_checkinteger(L, 1),l;
const char *data = lua_tolstring(L, 2, &l);
int n = platform_rcr_write(id, data, l);
lua_pushinteger(L, n);
return 1;
}
#endif
typedef enum pt_t { lfs_addr=0, lfs_size, spiffs_addr, spiffs_size, max_pt} pt_t;
LROT_BEGIN(pt)
LROT_NUMENTRY( lfs_addr, lfs_addr )
LROT_NUMENTRY( lfs_size, lfs_size )
LROT_NUMENTRY( spiffs_addr, spiffs_addr )
LROT_NUMENTRY( spiffs_size, spiffs_size )
LROT_END( pt, NULL, 0 )
// Lua: ptinfo = node.getpartitiontable()
static int node_getpartitiontable (lua_State *L) {
uint32_t param[max_pt] = {0};
param[lfs_size] = platform_flash_get_partition(NODEMCU_LFS0_PARTITION, param + lfs_addr);
param[spiffs_size] = platform_flash_get_partition(NODEMCU_SPIFFS0_PARTITION, param + spiffs_addr);
lua_settop(L, 0);
lua_createtable (L, 0, max_pt); /* at index 1 */
lua_pushrotable(L, (void*)pt_map); /* at index 2 */
lua_pushnil(L); /* first key at index 3 */
while (lua_next(L, 2) != 0) { /* key at index 3, and v at index 4 */
lua_pushvalue(L, 3); /* dup key to index 5 */
lua_pushinteger(L, param[lua_tointeger(L, 4)]); /* param [v] at index 6 */
lua_rawset(L, 1);
lua_pop(L, 1); /* discard v */
}
lua_pop(L, 1); /* discard pt_map reference */
return 1;
}
static void insert_partition(partition_item_t *p, int n, uint32_t type, uint32_t addr) {
if (n>0)
memmove(p+1, p, n*sizeof(partition_item_t)); /* overlapped so must be move not cpy */
p->type = type;
p->addr = addr;
p->size = 0;
}
static void delete_partition(partition_item_t *p, int n) {
if (n>0)
memmove(p, p+1, n*sizeof(partition_item_t)); /* overlapped so must be move not cpy */
}
#define SKIP (~0)
#define IROM0_PARTITION (SYSTEM_PARTITION_CUSTOMER_BEGIN + NODEMCU_IROM0TEXT_PARTITION)
#define LFS_PARTITION (SYSTEM_PARTITION_CUSTOMER_BEGIN + NODEMCU_LFS0_PARTITION)
#define SPIFFS_PARTITION (SYSTEM_PARTITION_CUSTOMER_BEGIN + NODEMCU_SPIFFS0_PARTITION)
// Lua: node.setpartitiontable(pt_settings)
static int node_setpartitiontable (lua_State *L) {
partition_item_t *rcr_pt = NULL, *pt;
uint32_t flash_size = flash_rom_get_size_byte();
uint32_t i = platform_rcr_read(PLATFORM_RCR_PT, (void **) &rcr_pt);
uint32_t last = 0;
uint32_t n = i / sizeof(partition_item_t);
uint32_t param[max_pt] = {SKIP, SKIP, SKIP, SKIP};
luaL_argcheck(L, lua_istable(L, 1), 1, "must be table");
lua_settop(L, 1);
/* convert input table into 4 option array */
lua_pushrotable(L, (void*)pt_map); /* at index 2 */
lua_pushnil(L); /* first key at index 3 */
while (lua_next(L, 1) != 0) {
/* 'key' (at index 3) and 'value' (at index 4) */
luaL_argcheck(L, lua_isstring(L, 3) && lua_isnumber(L, 4), 1, "invalid partition setting");
lua_pushvalue(L, 3); /* dup key to index 5 */
lua_rawget(L, 2); /* lookup in pt_map */
luaL_argcheck(L, !lua_isnil(L, -1), 1, "invalid partition setting");
param[lua_tointeger(L, 5)] = lua_tointeger(L, 4);
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(L, 2); /* discard value and lookup */
}
/*
* Allocate a scratch Partition Table as userdata on the Lua stack, and copy the
* current Flash PT into this for manipulation
*/
lua_newuserdata(L, (n+2)*sizeof(partition_item_t));
pt = lua_touserdata (L, -1);
memcpy(pt, rcr_pt, n*sizeof(partition_item_t));
pt[n].type = 0; pt[n+1].type = 0;
for (i = 0; i < n; i ++) {
partition_item_t *p = pt + i;
if (p->type == IROM0_PARTITION && p[1].type != LFS_PARTITION) {
// if the LFS partition is not following IROM0 then slot a blank one in
insert_partition(p + 1, n-i-1, LFS_PARTITION, p->addr + p->size);
n++;
} else if (p->type == LFS_PARTITION) {
if (p[1].type != SPIFFS_PARTITION) {
// if the SPIFFS partition is not following LFS then slot a blank one in
insert_partition(p + 1, n-i-1, SPIFFS_PARTITION, 0);
n++;
}
// update the LFS options if set
if (param[lfs_addr] != SKIP) {
p->addr = param[lfs_addr];
}
if (param[lfs_size] != SKIP) {
p->size = param[lfs_size];
}
} else if (p->type == SPIFFS_PARTITION) {
// update the SPIFFS options if set
if (param[spiffs_addr] != SKIP) {
p->addr = param[spiffs_addr];
p->size = SKIP;
}
if (param[spiffs_size] != SKIP) {
// BOTCH: - at the moment the firmware doesn't boot if the SPIFFS partition
// is deleted so the minimum SPIFFS size is 64Kb
p->size = param[spiffs_size] > 0x10000 ? param[spiffs_size] : 0x10000;
}
if (p->size == SKIP) {
if (p->addr < 0) {
// This allocate all the remaining flash to SPIFFS
p->addr = last;
p->size = flash_size - last;
} else {
p->size = flash_size - p->addr;
}
} else if (/* size is specified && */ p->addr == 0) {
// if the is addr not specified then start SPIFFS at 1Mb
// boundary if the size will fit otherwise make it consecutive
// to the previous partition.
p->addr = (p->size <= flash_size - 0x100000) ? 0x100000 : last;
}
}
if (p->size == 0) {
// Delete 0-sized partitions as the SDK barfs on these
delete_partition(p, n-i-1);
n--; i--;
} else {
// Do consistency tests on the partition
if (p->addr & (INTERNAL_FLASH_SECTOR_SIZE - 1) ||
p->size & (INTERNAL_FLASH_SECTOR_SIZE - 1) ||
p->addr < last ||
p->addr + p->size > flash_size) {
luaL_error(L, "value out of range");
}
}
}
// for (i = 0; i < n; i ++)
// dbg_printf("Partition %d: %04x %06x %06x\n", i, pt[i].type, pt[i].addr, pt[i].size);
platform_rcr_write(PLATFORM_RCR_PT, pt, n*sizeof(partition_item_t));
while(1); // Trigger WDT; the new PT will be loaded on reboot
return 0;
}
// Module function map
LROT_BEGIN(node_egc)
LROT_FUNCENTRY( meminfo, node_egc_meminfo )
LROT_FUNCENTRY( setmode, node_egc_setmode )
LROT_NUMENTRY( NOT_ACTIVE, EGC_NOT_ACTIVE )
LROT_NUMENTRY( ON_ALLOC_FAILURE, EGC_ON_ALLOC_FAILURE )
LROT_NUMENTRY( ON_MEM_LIMIT, EGC_ON_MEM_LIMIT )
LROT_NUMENTRY( ALWAYS, EGC_ALWAYS )
LROT_END( node_egc, NULL, 0 )
LROT_BEGIN(node_task)
LROT_FUNCENTRY( post, node_task_post )
LROT_NUMENTRY( LOW_PRIORITY, TASK_PRIORITY_LOW )
LROT_NUMENTRY( MEDIUM_PRIORITY, TASK_PRIORITY_MEDIUM )
LROT_NUMENTRY( HIGH_PRIORITY, TASK_PRIORITY_HIGH )
LROT_END( node_task, NULL, 0 )
LROT_BEGIN(node)
LROT_FUNCENTRY( heap, node_heap )
LROT_FUNCENTRY( info, node_info )
LROT_TABENTRY( task, node_task )
LROT_FUNCENTRY( flashreload, luaN_reload_reboot )
LROT_FUNCENTRY( flashindex, luaN_index )
LROT_FUNCENTRY( restart, node_restart )
LROT_FUNCENTRY( dsleep, node_deepsleep )
LROT_FUNCENTRY( dsleepMax, dsleepMax )
LROT_FUNCENTRY( sleep, node_sleep )
#ifdef PMSLEEP_ENABLE
PMSLEEP_INT_MAP
#endif
#ifdef DEVELOPMENT_TOOLS
LROT_FUNCENTRY( readrcr, node_readrcr )
LROT_FUNCENTRY( writercr, node_writercr )
#endif
LROT_FUNCENTRY( chipid, node_chipid )
LROT_FUNCENTRY( flashid, node_flashid )
LROT_FUNCENTRY( flashsize, node_flashsize )
LROT_FUNCENTRY( input, node_input )
LROT_FUNCENTRY( output, node_output )
// Moved to adc module, use adc.readvdd33()
// LROT_FUNCENTRY( readvdd33, node_readvdd33 )
LROT_FUNCENTRY( compile, node_compile )
LROT_NUMENTRY( CPU80MHZ, CPU80MHZ )
LROT_NUMENTRY( CPU160MHZ, CPU160MHZ )
LROT_FUNCENTRY( setcpufreq, node_setcpufreq )
LROT_FUNCENTRY( getcpufreq, node_getcpufreq )
LROT_FUNCENTRY( bootreason, node_bootreason )
LROT_FUNCENTRY( restore, node_restore )
LROT_FUNCENTRY( random, node_random )
#ifdef LUA_OPTIMIZE_DEBUG
LROT_FUNCENTRY( stripdebug, node_stripdebug )
#endif
LROT_TABENTRY( egc, node_egc )
#ifdef DEVELOPMENT_TOOLS
LROT_FUNCENTRY( osprint, node_osprint )
#endif
LROT_FUNCENTRY( getpartitiontable, node_getpartitiontable )
LROT_FUNCENTRY( setpartitiontable, node_setpartitiontable )
// Combined to dsleep(us, option)
// LROT_FUNCENTRY( dsleepsetoption, node_deepsleep_setoption )
LROT_END( node, NULL, 0 )
NODEMCU_MODULE(NODE, "node", node, NULL);