Unverified Commit 1f2e5bba authored by Terry Ellison's avatar Terry Ellison Committed by GitHub
Browse files

Implement panic call handling for all modules (#3163)

parent 4e689e98
......@@ -200,7 +200,7 @@ static void cron_handle_time(uint8_t mon, uint8_t dom, uint8_t dow, uint8_t hour
if ((ent->desc.min & desc.min ) == 0) continue;
lua_rawgeti(L, LUA_REGISTRYINDEX, ent->cb_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, cronent_list[i]);
lua_call(L, 1, 0);
luaL_pcallx(L, 1, 0);
}
}
......
......@@ -54,7 +54,8 @@ static int call_encoder( lua_State* L, const char *function ) {
lua_getfield(L, -1, function);
lua_insert(L, 1); //move function below the argument
lua_pop(L, 1); //and dump the encoder rotable from stack.
lua_call(L,1,1); // call encoder.xxx(string)
lua_call(L,1,1); // Normal call encoder.xxx(string)
// (errors thrown back to caller)
return 1;
}
......
......@@ -53,13 +53,13 @@ void notifyDccReset(uint8_t hardReset ) {
lua_State* L = lua_getstate();
cbInit(L, DCC_RESET);
cbAddFieldInteger(L, hardReset, "hardReset");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccIdle(void) {
lua_State* L = lua_getstate();
cbInit(L, DCC_IDLE);
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps ) {
......@@ -70,7 +70,7 @@ void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_D
cbAddFieldInteger(L, Speed, "Speed");
cbAddFieldInteger(L, Dir, "Dir");
cbAddFieldInteger(L, SpeedSteps, "SpeedSteps");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccSpeedRaw( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Raw) {
......@@ -79,7 +79,7 @@ void notifyDccSpeedRaw( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Raw) {
cbAddFieldInteger(L, Addr, "Addr");
cbAddFieldInteger(L, AddrType, "AddrType");
cbAddFieldInteger(L, Raw, "Raw");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
......@@ -89,7 +89,7 @@ void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uin
cbAddFieldInteger(L, AddrType, "AddrType");
cbAddFieldInteger(L, FuncGrp, "FuncGrp");
cbAddFieldInteger(L, FuncState, "FuncState");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccAccTurnoutBoard( uint16_t BoardAddr, uint8_t OutputPair, uint8_t Direction, uint8_t OutputPower ) {
......@@ -99,7 +99,7 @@ void notifyDccAccTurnoutBoard( uint16_t BoardAddr, uint8_t OutputPair, uint8_t D
cbAddFieldInteger(L, OutputPair, "OutputPair");
cbAddFieldInteger(L, Direction, "Direction");
cbAddFieldInteger(L, OutputPower, "OutputPower");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {
......@@ -108,28 +108,28 @@ void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t Output
cbAddFieldInteger(L, Addr, "Addr");
cbAddFieldInteger(L, Direction, "Direction");
cbAddFieldInteger(L, OutputPower, "OutputPower");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccAccBoardAddrSet( uint16_t BoardAddr) {
lua_State* L = lua_getstate();
cbInit(L, DCC_ACCESSORY);
cbAddFieldInteger(L, BoardAddr, "BoardAddr");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccAccOutputAddrSet( uint16_t Addr) {
lua_State* L = lua_getstate();
cbInit(L, DCC_ACCESSORY);
cbAddFieldInteger(L, Addr, "Addr");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccSigOutputState( uint16_t Addr, uint8_t State) {
lua_State* L = lua_getstate();
cbInit(L, DCC_ACCESSORY);
cbAddFieldInteger(L, State, "State");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyDccMsg( DCC_MSG * Msg ) {
......@@ -142,14 +142,14 @@ void notifyDccMsg( DCC_MSG * Msg ) {
ets_sprintf(field, "Data%d", i);
cbAddFieldInteger(L, Msg->Data[i], field);
}
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
void notifyServiceMode(bool InServiceMode){
lua_State* L = lua_getstate();
cbInit(L, DCC_SERVICEMODE);
cbAddFieldInteger(L, InServiceMode, "InServiceMode");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
}
// CV handling
......@@ -163,7 +163,8 @@ uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) {
lua_newtable(L);
cbAddFieldInteger(L, CV, "CV");
cbAddFieldInteger(L, Writable, "Writable");
lua_call(L, 2, 1);
if (luaL_pcallx(L, 2, 1) != LUA_OK)
return 0;
uint8 result = lua_tointeger(L, -1);
lua_pop(L, 1);
return result;
......@@ -177,7 +178,8 @@ uint8_t notifyCVRead( uint16_t CV) {
lua_pushinteger(L, CV_READ);
lua_newtable(L);
cbAddFieldInteger(L, CV, "CV");
lua_call(L, 2, 1);
if (luaL_pcallx(L, 2, 1) != LUA_OK)
return 0;;
uint8 result = lua_tointeger(L, -1);
lua_pop(L, 1);
return result;
......@@ -192,7 +194,7 @@ uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) {
lua_newtable(L);
cbAddFieldInteger(L, CV, "CV");
cbAddFieldInteger(L, Value, "Value");
lua_call(L, 2, 0);
luaL_pcallx(L, 2, 0);
return Value;
}
......@@ -202,7 +204,7 @@ void notifyCVResetFactoryDefault(void) {
return;
lua_rawgeti(L, LUA_REGISTRYINDEX, CV_cb);
lua_pushinteger(L, CV_RESET);
lua_call(L, 1, 0);
luaL_pcallx(L, 1, 0);
}
static int dcc_lua_setup(lua_State* L) {
......
......@@ -181,7 +181,7 @@ static void enduser_setup_debug(int line, const char *str)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, state->lua_dbg_cb_ref);
lua_pushfstring(L, "%d: \t%s", line, str);
lua_call(L, 1, 0);
luaL_pcallx(L, 1, 0);
}
}
......@@ -196,7 +196,7 @@ static void enduser_setup_error(int line, const char *str, int err)
lua_rawgeti (L, LUA_REGISTRYINDEX, state->lua_err_cb_ref);
lua_pushnumber(L, err);
lua_pushfstring(L, "%d: \t%s", line, str);
lua_call (L, 2, 0);
luaL_pcallx (L, 2, 0);
}
}
......@@ -209,7 +209,7 @@ static void enduser_setup_connected_callback()
if (state != NULL && state->lua_connected_cb_ref != LUA_NOREF)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, state->lua_connected_cb_ref);
lua_call(L, 0, 0);
luaL_pcallx(L, 0, 0);
}
}
......
......@@ -60,7 +60,8 @@ static sint32_t file_rtc_cb( vfs_time *tm )
lua_State *L = lua_getstate();
lua_rawgeti( L, LUA_REGISTRYINDEX, rtc_cb_ref );
lua_call( L, 0, 1 );
if (luaL_pcallx( L, 0, 1 ) != LUA_OK)
return res;
if (lua_type( L, lua_gettop( L ) ) == LUA_TTABLE) {
table2tm( L, tm );
......
......@@ -77,7 +77,8 @@ static void gpio_intr_callback_task (task_param_t param, uint8 priority)
then = system_get_time() & 0x7fffffff;
}
lua_call(L, 3, 0);
if(luaL_pcallx(L, 3, 0) != LUA_OK)
return;
}
if (INTERRUPT_TYPE_IS_LEVEL(pin_int_type[pin])) {
......@@ -237,10 +238,7 @@ static void seroutasync_done (task_param_t arg)
lua_rawgeti (L, LUA_REGISTRYINDEX, serout.lua_done_ref);
luaL_unref (L, LUA_REGISTRYINDEX, serout.lua_done_ref);
serout.lua_done_ref = LUA_NOREF;
if (lua_pcall(L, 0, 0, 0)) {
// Uncaught Error. Print instead of sudden reset
luaL_error(L, "error: %s", lua_tostring(L, -1));
}
luaL_pcallx(L, 0, 0);
}
}
......
......@@ -463,7 +463,7 @@ static void gpio_pulse_task(os_param_t param, uint8_t prio)
active_pulser_ref = LUA_NOREF;
luaL_unref(L, LUA_REGISTRYINDEX, pulser_ref);
lua_call(L, rc, 0);
luaL_pcallx(L, rc, 0);
}
}
......
......@@ -100,7 +100,7 @@ static void http_callback( char * response, int http_status, char ** full_respon
luaL_unref(L, LUA_REGISTRYINDEX, http_callback_registry);
http_callback_registry = LUA_NOREF;
lua_call(L, 3, 0); // With 3 arguments and 0 result
luaL_pcallx(L, 3, 0); // With 3 arguments and 0 result
}
}
......
......@@ -258,7 +258,7 @@ static void hx711_task(platform_task_param_t param, uint8_t prio)
control->freed = param;
lua_call(L, 3, 0);
luaL_pcallx(L, 3, 0);
}
}
#endif
......
......@@ -21,6 +21,39 @@
#define CPU80MHZ 80
#define CPU160MHZ 160
#define DELAY2SEC 2000
static void restart_callback(void *arg) {
UNUSED(arg);
system_restart();
}
static int default_onerror(lua_State *L) {
static os_timer_t restart_timer = {0};
/* Use Lua print to print the ToS */
lua_settop(L, 1);
lua_getglobal(L, "print");
lua_insert(L, 1);
lua_pcall(L, 1, 0, 0);
/* One first time through set automatic restart after 2s delay */
if (!restart_timer.timer_func) {
os_timer_setfn(&restart_timer, restart_callback, NULL);
os_timer_arm(&restart_timer, DELAY2SEC, 0);
}
return 0;
}
// Lua: setonerror([function])
static int node_setonerror( lua_State* L ) {
lua_settop(L, 1);
if (!lua_isfunction(L, 1)) {
lua_pop(L, 1);
lua_pushcfunction(L, default_onerror);
}
lua_setfield(L, LUA_REGISTRYINDEX, "onerror");
return 0;
}
// Lua: startupcommand(string)
static int node_startupcommand( lua_State* L ) {
size_t l, lrcr;
......@@ -229,12 +262,17 @@ static int node_input( lua_State* L ) {
lua_rawgeti(L, -1, 1); /* get the pipe_write func from stdin[1] */
lua_insert(L, -2); /* and move above the pipe ref */
lua_pushvalue(L, 1);
lua_call(L, 2, 0); /* stdin:write(line) */
lua_call(L, 2, 0); /* stdin:write(line); errors are thrown to caller */
return 0;
}
static int serial_debug = 1;
/*
** Output redirector. Note that panics in the output callback cannot be processed
** using luaL_pcallx() as this would create an infinite error loop, so they are
** reported direct to the UART.
*/
void output_redirect(const char *str, size_t l) {
lua_State *L = lua_getstate();
int n = lua_gettop(L);
......@@ -247,8 +285,10 @@ void output_redirect(const char *str, size_t l) {
lua_rawgeti(L, -1, 1); /* get the pipe_write func from stdout[1] */
lua_insert(L, -2); /* and move above the pipe ref */
lua_pushlstring(L, str, l);
lua_call(L, 2, 0); /* Reg.stdout:write(str) */
if (lua_pcall(L, 2, 0, 0) != LUA_OK) { /* Reg.stdout:write(str) */
lua_writestringerror("error calling stdout:write(%s)\n", lua_tostring(L, -1));
system_restart();
}
} else { /* reg.stdout == nil */
uart0_sendStrn(str, l);
}
......@@ -266,7 +306,7 @@ static int node_output( lua_State* L )
lua_pushcfunction(L, pipe_create);
lua_insert(L, 1);
lua_pushinteger(L, LUA_TASK_MEDIUM);
lua_call(L, 2, 1); /* T[1] = pipe.create(CB, medium_priority) */
lua_call(L, 2, 1); /* Any pipe.create() errors thrown back to caller */
} else { // remove the stdout pipe
lua_pop(L,1);
lua_pushnil(L); /* T[1] = nil */
......@@ -786,8 +826,9 @@ LROT_BEGIN(node, NULL, 0)
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( flashreload, lua_lfsreload )
LROT_FUNCENTRY( flashindex, lua_lfsindex )
LROT_FUNCENTRY( setonerror, node_setonerror )
LROT_FUNCENTRY( startupcommand, node_startupcommand )
LROT_FUNCENTRY( restart, node_restart )
LROT_FUNCENTRY( dsleep, node_deepsleep )
......@@ -831,5 +872,9 @@ LROT_BEGIN(node, NULL, 0)
// LROT_FUNCENTRY( dsleepsetoption, node_deepsleep_setoption )
LROT_END(node, NULL, 0)
int luaopen_node( lua_State *L ) {
lua_settop(L, 0);
return node_setonerror(L); /* set default onerror action */
}
NODEMCU_MODULE(NODE, "node", node, NULL);
NODEMCU_MODULE(NODE, "node", node, luaopen_node);
......@@ -27,7 +27,7 @@ static void dispatch_callback( lua_State *L, int self_ref, int cb_ref, int retur
if (cb_ref != LUA_NOREF) {
lua_rawgeti( L, LUA_REGISTRYINDEX, cb_ref );
lua_rawgeti( L, LUA_REGISTRYINDEX, self_ref );
lua_call( L, 1, returns );
luaL_pcallx( L, 1, returns );
}
}
......
......@@ -185,7 +185,7 @@ static int pipe_write_and_read_poster (lua_State *L) {
lua_replace(L, UVstate);
lua_pushvalue(L, UVfunc); /* Lua CB function */
lua_pushvalue(L, UVpipe); /* pipe table */
lua_call(L, 1, 1);
lua_call(L, 1, 1); /* Errors are thrown back to caller */
/*
* On return from the Lua CB, the task is never reposted if the pipe is empty.
* If it is not empty then the Lua CB return status determines when reposting
......
......@@ -114,7 +114,7 @@ static void callback_callOne(lua_State* L, int cb, int mask, int arg, uint32_t t
lua_pushinteger(L, arg);
lua_pushinteger(L, time);
lua_call(L, 3, 0);
luaL_pcallx(L, 3, 0);
}
}
......
......@@ -211,7 +211,7 @@ static void handle_error (lua_State *L, ntp_err_t err, const char *msg)
lua_pushinteger (L, err);
lua_pushstring (L, msg);
cleanup (L);
lua_call (L, 2, 0);
luaL_pcallx (L, 2, 0);
}
else
cleanup (L);
......@@ -319,7 +319,7 @@ static void sntp_handle_result(lua_State *L) {
if (have_cb)
{
lua_call (L, 4, 0);
luaL_pcallx (L, 4, 0);
}
}
......
......@@ -287,7 +287,7 @@ static void softuart_rx_callback(task_param_t arg)
}
lua_pushlstring(L, softuart_rx_buffer, buffer_lenght);
softuart->armed = 1;
lua_call(L, 1, 0);
luaL_pcallx(L, 1, 0);
}
// Arguments: event name, minimum buffer filled to run callback, callback function
......
......@@ -92,7 +92,7 @@ static void somfy_transmissionDone (task_param_t arg)
lua_rawgeti (L, LUA_REGISTRYINDEX, lua_done_ref);
luaL_unref (L, LUA_REGISTRYINDEX, lua_done_ref);
lua_done_ref = LUA_NOREF;
lua_call (L, 0, 0);
luaL_pcallx (L, 0, 0);
}
static void ICACHE_RAM_ATTR sendCommand(os_param_t p) {
......
......@@ -47,7 +47,7 @@ static void callback_execute(lua_State* L, unsigned int id)
lua_rawgeti(L, LUA_REGISTRYINDEX, callback);
callback_free(L, id);
lua_call(L, 0, 0);
luaL_pcallx(L, 0, 0);
}
}
......
......@@ -188,7 +188,7 @@ uint8_t tcs34725EnableDone()
lua_rawgeti(L, LUA_REGISTRYINDEX, cb_tcs_en); // Get the callback to call
luaL_unref(L, LUA_REGISTRYINDEX, cb_tcs_en); // Unregister the callback to avoid leak
cb_tcs_en = LUA_NOREF;
lua_call(L, 0, 0);
luaL_pcallx(L, 0, 0);
return 0;
}
......
......@@ -10,8 +10,9 @@
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <ctype.h>
#include "mem.h"
#include "lwip/ip_addr.h"
#include "espconn.h"
......@@ -463,12 +464,11 @@ static const char *fill_page_with_pem(lua_State *L, const unsigned char *flash_m
static int tls_cert_auth(lua_State *L)
{
if (ssl_client_options.cert_auth_callback != LUA_NOREF) {
lua_unref(L, ssl_client_options.cert_auth_callback);
luaL_unref(L, LUA_REGISTRYINDEX, ssl_client_options.cert_auth_callback);
ssl_client_options.cert_auth_callback = LUA_NOREF;
}
if ((lua_type(L, 1) == LUA_TFUNCTION)
|| (lua_type(L, 1) == LUA_TLIGHTFUNCTION)) {
ssl_client_options.cert_auth_callback = lua_ref(L, 1);
if (lua_type(L, 1) == LUA_TFUNCTION) {
ssl_client_options.cert_auth_callback = luaL_ref(L, LUA_REGISTRYINDEX);
lua_pushboolean(L, true);
return 1;
}
......@@ -518,12 +518,11 @@ static int tls_cert_auth(lua_State *L)
static int tls_cert_verify(lua_State *L)
{
if (ssl_client_options.cert_verify_callback != LUA_NOREF) {
lua_unref(L, ssl_client_options.cert_verify_callback);
luaL_unref(L, LUA_REGISTRYINDEX, ssl_client_options.cert_verify_callback);
ssl_client_options.cert_verify_callback = LUA_NOREF;
}
if ((lua_type(L, 1) == LUA_TFUNCTION)
|| (lua_type(L, 1) == LUA_TLIGHTFUNCTION)) {
ssl_client_options.cert_verify_callback = lua_ref(L, 1);
if (lua_type(L, 1) == LUA_TFUNCTION) {
ssl_client_options.cert_verify_callback = luaL_ref(L, LUA_REGISTRYINDEX);
lua_pushboolean(L, true);
return 1;
}
......
......@@ -5,48 +5,7 @@
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
/*-------------------------------------
NEW TIMER API
---------------------------------------
tmr.wdclr() -- not changed
tmr.now() -- not changed
tmr.time() -- not changed
tmr.delay() -- not changed
tmr.alarm() -- not changed
tmr.stop() -- changed, see below. use tmr.unregister for old functionality
tmr.register(ref, interval, mode, function)
bind function with timer and set the interval in ms
the mode can be:
tmr.ALARM_SINGLE for a single run alarm
tmr.ALARM_SEMI for a multiple single run alarm
tmr.ALARM_AUTO for a repating alarm
tmr.register does NOT start the timer
tmr.alarm is a tmr.register & tmr.start macro
tmr.unregister(ref)
stop alarm, unbind function and clean up memory
not needed for ALARM_SINGLE, as it unregisters itself
tmr.start(ref)
ret: bool
start a alarm, returns true on success
tmr.stop(ref)
ret: bool
stops a alarm, returns true on success
this call dose not free any memory, to do so use tmr.unregister
stopped alarms can be started with start
tmr.interval(ref, interval)
set alarm interval, running alarm will be restarted
tmr.state(ref)
ret: (bool, int) or nil
returns alarm status (true=started/false=stopped) and mode
nil if timer is unregistered
tmr.softwd(int)
set a negative value to stop the timer
any other value starts the timer, when the
countdown reaches zero, the device restarts
the timer units are seconds
*/
/* See docs/modules/tmr.md for documentaiton o current API */
#include "module.h"
#include "lauxlib.h"
......@@ -55,40 +14,40 @@ tmr.softwd(int)
#include "user_interface.h"
#include "pm/swtimer.h"
#define TIMER_MODE_OFF 3
#define TIMER_MODE_SINGLE 0
#define TIMER_MODE_SEMI 2
#define TIMER_MODE_AUTO 1
#define TIMER_MODE_AUTO 1
#define TIMER_MODE_SEMI 2
#define TIMER_MODE_OFF 3
#define TIMER_IDLE_FLAG (1<<7)
#define STRINGIFY_VAL(x) #x
#define STRINGIFY(x) STRINGIFY_VAL(x)
// assuming system_timer_reinit() has *not* been called
#define MAX_TIMEOUT_DEF 6870947 //SDK 1.5.3 limit (0x68D7A3)
#define MAX_TIMEOUT_DEF 0x68D7A3 // SDK specfied limit
static const uint32 MAX_TIMEOUT=MAX_TIMEOUT_DEF;
static const char* MAX_TIMEOUT_ERR_STR = "Range: 1-"STRINGIFY(MAX_TIMEOUT_DEF);
typedef struct{
os_timer_t os;
sint32_t lua_ref; /* Reference to the callback function */
sint32_t self_ref; /* Reference to this structure as userdata */
sint32_t lua_ref; /* Reference to registered callback function */
sint32_t self_ref; /* Reference to UD registered slot */
uint32_t interval;
uint8_t mode;
}timer_struct_t;
typedef timer_struct_t* tmr_t;
} tmr_t;
// The previous implementation extended the rtc counter to 64 bits, and then
// applied rtc2sec with the current calibration value to that 64 bit value.
// This means that *ALL* clock ticks since bootup are counted with the *current*
// clock period. In extreme cases (long uptime, sudden temperature change), this
// could result in tmr.time() going backwards....
// This implementation instead applies rtc2usec to short time intervals only (the
// longest being around 1 second), and then accumulates the resulting microseconds
// in a 64 bit counter. That's guaranteed to be monotonic, and should be a lot closer
// to representing an actual uptime.
// This means that *ALL* clock ticks since bootup are counted with the
// *current* clock period. In extreme cases (long uptime, sudden temperature
// change), this could result in tmr.time() going backwards....
//
// This implementation instead applies rtc2usec to short time intervals only
// (the longest being around 1 second), and then accumulates the resulting
// microseconds in a 64 bit counter. That's guaranteed to be monotonic, and
// should be a lot closer to representing an actual uptime.
static uint32_t rtc_time_cali=0;
static uint32_t last_rtc_time=0;
static uint64_t last_rtc_time_us=0;
......@@ -97,180 +56,137 @@ static sint32_t soft_watchdog = -1;
static os_timer_t rtc_timer;
static void alarm_timer_common(void* arg){
tmr_t tmr = (tmr_t)arg;
lua_State* L = lua_getstate();
if(tmr->lua_ref == LUA_NOREF)
return;
lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->lua_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->self_ref);
//if the timer was set to single run we clean up after it
if(tmr->mode == TIMER_MODE_SINGLE){
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
tmr->lua_ref = LUA_NOREF;
tmr->mode = TIMER_MODE_OFF;
}else if(tmr->mode == TIMER_MODE_SEMI){
tmr->mode |= TIMER_IDLE_FLAG;
}
if (tmr->mode != TIMER_MODE_AUTO && tmr->self_ref != LUA_REFNIL) {
luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref);
tmr->self_ref = LUA_NOREF;
}
lua_call(L, 1, 0);
tmr_t *tmr = (tmr_t *) arg;
if(tmr->lua_ref > 0) {
lua_State* L = lua_getstate();
lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->lua_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->self_ref);
if (tmr->mode != TIMER_MODE_AUTO) {
if(tmr->mode == TIMER_MODE_SINGLE) {
luaL_unref2(L, LUA_REGISTRYINDEX, tmr->lua_ref);
luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref);
tmr->mode = TIMER_MODE_OFF;
} else if (tmr->mode == TIMER_MODE_SEMI) {
tmr->mode |= TIMER_IDLE_FLAG;
luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref);
}
}
luaL_pcallx(L, 1, 0);
}
}
// Lua: tmr.delay( us )
static int tmr_delay( lua_State* L ){
sint32_t us = luaL_checkinteger(L, 1);
if(us <= 0)
return luaL_error(L, "wrong arg range");
while(us >= 1000000){
us -= 1000000;
os_delay_us(1000000);
system_soft_wdt_feed ();
luaL_argcheck(L, us>0, 1, "wrong arg range");
while(us > 0){
os_delay_us(us >= 1000000 ? 1000000 : us);
system_soft_wdt_feed ();
us -= 1000000;
}
if(us>0){
os_delay_us(us);
system_soft_wdt_feed ();
}
return 0;
return 0;
}
// Lua: tmr.now() , return system timer in us
static int tmr_now(lua_State* L){
uint32_t now = 0x7FFFFFFF & system_get_time();
lua_pushinteger(L, now);
lua_pushinteger(L, (uint32_t) (0x7FFFFFFF & system_get_time()));
return 1;
}
// Lua: tmr.ccount() , returns CCOUNT register
static int tmr_ccount( lua_State* L )
{
static int tmr_ccount(lua_State* L){
lua_pushinteger(L, CCOUNT_REG);
return 1;
}
static tmr_t tmr_get( lua_State *L, int stack ) {
tmr_t t = (tmr_t)luaL_checkudata(L, stack, "tmr.timer");
if (t == NULL)
return (tmr_t)luaL_error(L, "timer object expected");
return t;
}
// Lua: tmr.register( ref, interval, mode, function )
static int tmr_register(lua_State* L){
tmr_t tmr = tmr_get(L, 1);
/*
** Health warning: this is also called DIRECTLY from alarm() which assumes that the Lua
** stack is preserved for the following start(), so the stack MUST be balanced here.
*/
// Lua: t:register( interval, mode, function )
static int tmr_register(lua_State* L) {
tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer");
uint32_t interval = luaL_checkinteger(L, 2);
uint8_t mode = luaL_checkinteger(L, 3);
luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR);
luaL_argcheck(L, (mode == TIMER_MODE_SINGLE || mode == TIMER_MODE_SEMI || mode == TIMER_MODE_AUTO), 3, "Invalid mode");
luaL_argcheck(L, lua_isfunction(L, 4), 4, "Must be function");
//get the lua function reference
lua_pushvalue(L, 4);
sint32_t ref = luaL_ref(L, LUA_REGISTRYINDEX);
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
os_timer_disarm(&tmr->os);
//there was a bug in this part, the second part of the following condition was missing
if(tmr->lua_ref != LUA_NOREF && tmr->lua_ref != ref)
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
tmr->lua_ref = ref;
luaL_reref(L, LUA_REGISTRYINDEX, &tmr->lua_ref);
tmr->mode = mode|TIMER_IDLE_FLAG;
tmr->interval = interval;
os_timer_setfn(&tmr->os, alarm_timer_common, tmr);
return 0;
}
// Lua: tmr.start( id / ref )
// Lua: t:start()
static int tmr_start(lua_State* L){
tmr_t tmr = tmr_get(L, 1);
tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer");
int idle = tmr->mode & TIMER_IDLE_FLAG;
if (tmr->self_ref == LUA_NOREF) {
lua_pushvalue(L, 1);
lua_settop(L, 1); /* ignore any args after the userdata */
if (tmr->self_ref == LUA_NOREF)
tmr->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
//we return false if the timer is not idle
if(!(tmr->mode&TIMER_IDLE_FLAG)){
lua_pushboolean(L, 0);
}else{
tmr->mode &= ~TIMER_IDLE_FLAG;
if(idle) {
tmr->mode &= ~TIMER_IDLE_FLAG;
os_timer_arm(&tmr->os, tmr->interval, tmr->mode==TIMER_MODE_AUTO);
lua_pushboolean(L, 1);
}
}
lua_pushboolean(L, !idle); /* false if the timer is not idle */
return 1;
}
// Lua: tmr.alarm( id / ref, interval, repeat, function )
// Lua: t:alarm( interval, repeat, function )
static int tmr_alarm(lua_State* L){
tmr_register(L);
return tmr_start(L);
}
// Lua: tmr.stop( id / ref )
// Lua: t:stop()
static int tmr_stop(lua_State* L){
tmr_t tmr = tmr_get(L, 1);
tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer");
int idle = tmr->mode == TIMER_MODE_OFF || (tmr->mode & TIMER_IDLE_FLAG);
luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref);
if (tmr->self_ref != LUA_REFNIL) {
luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref);
tmr->self_ref = LUA_NOREF;
}
//we return false if the timer is idle (of not registered)
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF){
tmr->mode |= TIMER_IDLE_FLAG;
if(!idle)
os_timer_disarm(&tmr->os);
lua_pushboolean(L, 1);
}else{
lua_pushboolean(L, 0);
}
tmr->mode |= TIMER_IDLE_FLAG;
lua_pushboolean(L, !idle); /* return false if the timer is idle (or not registered) */
return 1;
}
#ifdef TIMER_SUSPEND_ENABLE
#define TMR_SUSPEND_REMOVED_MSG "This feature has been removed, we apologize for any inconvenience this may have caused."
static int tmr_suspend(lua_State* L){
#define tmr_suspend tmr_suspend_removed
#define tmr_resume tmr_suspend_removed
#define tmr_suspend_all tmr_suspend_removed
#define tmr_resume_all tmr_suspend_removed
static int tmr_suspend_removed(lua_State* L){
return luaL_error(L, TMR_SUSPEND_REMOVED_MSG);
}
static int tmr_resume(lua_State* L){
return luaL_error(L, TMR_SUSPEND_REMOVED_MSG);
}
static int tmr_suspend_all (lua_State *L){
return luaL_error(L, TMR_SUSPEND_REMOVED_MSG);
}
static int tmr_resume_all (lua_State *L){
return luaL_error(L, TMR_SUSPEND_REMOVED_MSG);
}
#endif
// Lua: tmr.unregister( id / ref )
// Lua: t:unregister()
static int tmr_unregister(lua_State* L){
tmr_t tmr = tmr_get(L, 1);
if (tmr->self_ref != LUA_REFNIL) {
luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref);
tmr->self_ref = LUA_NOREF;
}
tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer");
luaL_unref2(L, LUA_REGISTRYINDEX, tmr->self_ref);
luaL_unref2(L, LUA_REGISTRYINDEX, tmr->lua_ref);
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
os_timer_disarm(&tmr->os);
if(tmr->lua_ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
tmr->lua_ref = LUA_NOREF;
tmr->mode = TIMER_MODE_OFF;
return 0;
}
// Lua: tmr.interval( id / ref, interval )
// Lua: t:interval( interval )
static int tmr_interval(lua_State* L){
tmr_t tmr = tmr_get(L, 1);
tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer");
uint32_t interval = luaL_checkinteger(L, 2);
luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR);
if(tmr->mode != TIMER_MODE_OFF){
......@@ -283,10 +199,9 @@ static int tmr_interval(lua_State* L){
return 0;
}
// Lua: tmr.state( id / ref )
// Lua: t:state()
static int tmr_state(lua_State* L){
tmr_t tmr = tmr_get(L, 1);
tmr_t *tmr = (tmr_t *) luaL_checkudata(L, 1, "tmr.timer");
if(tmr->mode == TIMER_MODE_OFF){
lua_pushnil(L);
return 1;
......@@ -297,28 +212,21 @@ static int tmr_state(lua_State* L){
return 2;
}
/*I left the led comments 'couse I don't know
why they are here*/
// extern void update_key_led();
// Lua: tmr.wdclr()
static int tmr_wdclr( lua_State* L ){
system_soft_wdt_feed ();
// update_key_led();
return 0;
}
//system_rtc_clock_cali_proc() returns
//a fixed point value (12 bit fraction part)
//it tells how many rtc clock ticks represent 1us.
//the high 64 bits of the uint64_t multiplication
//are unnedded (I did the math)
// The on ESP8266 system_rtc_clock_cali_proc() returns a fixed point value
// (12 bit fraction part), giving how many rtc clock ticks represent 1us.
// The high 64 bits of the uint64_t multiplication are not needed)
static uint32_t rtc2usec(uint64_t rtc){
return (rtc*rtc_time_cali)>>12;
}
// This returns the number of microseconds uptime. Note that it relies on the rtc clock,
// which is notoriously temperature dependent
// This returns the number of microseconds uptime. Note that it relies on
// the rtc clock, which is notoriously temperature dependent
inline static uint64_t rtc_timer_update(bool do_calibration){
if (do_calibration || rtc_time_cali==0)
rtc_time_cali=system_rtc_clock_cali_proc();
......@@ -330,8 +238,7 @@ inline static uint64_t rtc_timer_update(bool do_calibration){
// Only update if at least 100ms has passed since we last updated.
// This prevents the rounding errors in rtc2usec from accumulating
if (us_since_last>=100000)
{
if (us_since_last>=100000){
last_rtc_time=current;
last_rtc_time_us=now;
}
......@@ -356,20 +263,18 @@ static int tmr_time( lua_State* L ){
// Lua: tmr.softwd( value )
static int tmr_softwd( lua_State* L ){
soft_watchdog = luaL_checkinteger(L, 1);
int t = luaL_checkinteger(L, 1);
luaL_argcheck(L, t>0 , 2, "invalid time");
soft_watchdog = t;
return 0;
}
// Lua: tmr.create()
static int tmr_create( lua_State *L ) {
tmr_t ud = (tmr_t)lua_newuserdata(L, sizeof(timer_struct_t));
if (!ud) return luaL_error(L, "not enough memory");
tmr_t *ud = (tmr_t *)lua_newuserdata(L, sizeof(*ud));
luaL_getmetatable(L, "tmr.timer");
lua_setmetatable(L, -2);
ud->lua_ref = LUA_NOREF;
ud->self_ref = LUA_NOREF;
ud->mode = TIMER_MODE_OFF;
os_timer_disarm(&ud->os);
*ud = (tmr_t) {{0}, LUA_NOREF, LUA_NOREF, 0, TIMER_MODE_OFF};
return 1;
}
......@@ -422,13 +327,14 @@ int luaopen_tmr( lua_State *L ){
os_timer_setfn(&rtc_timer, rtc_callback, NULL);
os_timer_arm(&rtc_timer, 1000, 1);
// The function rtc_callback calls the a function that calibrates the SoftRTC
// for drift in the esp8266's clock. My guess: after the duration of light_sleep
// there is bound to be some drift in the clock, so a calibration is due.
SWTIMER_REG_CB(rtc_callback, SWTIMER_RESUME);
//The function rtc_callback calls the a function that calibrates the SoftRTC for drift in the esp8266's clock.
//My guess: after the duration of light_sleep there's bound to be some drift in the clock, so a calibration is due.
SWTIMER_REG_CB(alarm_timer_common, SWTIMER_RESUME);
//The function alarm_timer_common handles timers created by the developer via tmr.create().
//No reason not to resume the timers, so resume em'.
// The function alarm_timer_common handles timers created by the developer via
// tmr.create(). No reason not to resume the timers, so resume em'.
SWTIMER_REG_CB(alarm_timer_common, SWTIMER_RESUME);
return 0;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment