Unverified Commit 6db74142 authored by Terry Ellison's avatar Terry Ellison Committed by GitHub
Browse files

Merge branch 'dev' into dev-LFS

parents 88bd9e01 f427951f
......@@ -212,12 +212,15 @@ static void enduser_setup_connected_callback()
}
}
#include "pm/swtimer.h"
static void enduser_setup_check_station_start(void)
{
ENDUSER_SETUP_DEBUG("enduser_setup_check_station_start");
os_timer_setfn(&(state->check_station_timer), enduser_setup_check_station, NULL);
SWTIMER_REG_CB(enduser_setup_check_station, SWTIMER_RESUME);
//The function enduser_setup_check_station checks for a successful connection to the configured AP
//My guess: I'm not sure about whether or not user feedback is given via the web interface, but I don't see a problem with letting this timer resume.
os_timer_arm(&(state->check_station_timer), 3*1000, TRUE);
}
......@@ -317,6 +320,9 @@ static void enduser_setup_check_station(void *p)
if (!manual)
{
os_timer_setfn(&(state->shutdown_timer), enduser_setup_stop_callback, NULL);
SWTIMER_REG_CB(enduser_setup_stop_callback, SWTIMER_RESUME);
//The function enduser_setup_stop_callback frees services and resources used by enduser setup.
//My guess: Since it would lead to a memory leak, it's probably best to resume this timer.
os_timer_arm(&(state->shutdown_timer), 10*1000, FALSE);
}
}
......@@ -664,6 +670,8 @@ static int enduser_setup_http_handle_credentials(char *data, unsigned short data
struct station_config *cnf = luaM_malloc(lua_getstate(), sizeof(struct station_config));
c_memset(cnf, 0, sizeof(struct station_config));
cnf->threshold.rssi = -127;
cnf->threshold.authmode = AUTH_OPEN;
int err;
err = enduser_setup_http_urldecode(cnf->ssid, name_str_start, name_str_len, sizeof(cnf->ssid));
......
......@@ -981,6 +981,7 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
return espconn_status;
}
#include "pm/swtimer.h"
// Lua: mqtt:connect( host, port, secure, auto_reconnect, function(client), function(client, connect_return_code) )
static int mqtt_socket_connect( lua_State* L )
{
......@@ -1114,6 +1115,9 @@ static int mqtt_socket_connect( lua_State* L )
os_timer_disarm(&mud->mqttTimer);
os_timer_setfn(&mud->mqttTimer, (os_timer_func_t *)mqtt_socket_timer, mud);
SWTIMER_REG_CB(mqtt_socket_timer, SWTIMER_RESUME);
//I assume that mqtt_socket_timer connects to the mqtt server, but I'm not really sure what impact light_sleep will have on it.
//My guess: If in doubt, resume the timer
// timer started in socket_connect()
if((ipaddr.addr == IPADDR_NONE) && (c_memcmp(domain,"255.255.255.255",16) != 0))
......
......@@ -78,7 +78,7 @@ static int node_deepsleep( lua_State* L )
#ifdef PMSLEEP_ENABLE
#include "pmSleep.h"
#include "pm/pmSleep.h"
int node_sleep_resume_cb_ref= LUA_NOREF;
void node_sleep_resume_cb(void)
......@@ -91,6 +91,7 @@ void node_sleep_resume_cb(void)
// 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;
......@@ -103,6 +104,10 @@ static int node_sleep( lua_State* L )
cfg.resume_cb_ptr = &node_sleep_resume_cb;
pmSleep_suspend(&cfg);
#else
c_printf("\n The option \"timer_suspend_enable\" in \"app/include/user_config.h\" was disabled during FW build!\n");
return luaL_error(L, "light sleep is unavailable");
#endif
return 0;
}
#endif //PMSLEEP_ENABLE
......@@ -463,14 +468,23 @@ static int node_stripdebug (lua_State *L) {
// See legc.h and lecg.c.
static int node_egc_setmode(lua_State* L) {
unsigned mode = luaL_checkinteger(L, 1);
unsigned limit = luaL_optinteger (L, 2, 0);
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");
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
......@@ -561,6 +575,7 @@ static int node_random (lua_State *L) {
// Module function map
static const LUA_REG_TYPE node_egc_map[] = {
{ LSTRKEY( "meminfo" ), LFUNCVAL( node_egc_meminfo ) },
{ LSTRKEY( "setmode" ), LFUNCVAL( node_egc_setmode ) },
{ LSTRKEY( "NOT_ACTIVE" ), LNUMVAL( EGC_NOT_ACTIVE ) },
{ LSTRKEY( "ON_ALLOC_FAILURE" ), LNUMVAL( EGC_ON_ALLOC_FAILURE ) },
......
......@@ -129,6 +129,8 @@ int platform_rotary_exists( unsigned int id )
return (id < ROTARY_CHANNEL_COUNT);
}
#include "pm/swtimer.h"
// Lua: setup(id, phase_a, phase_b [, press])
static int lrotary_setup( lua_State* L )
{
......@@ -152,7 +154,14 @@ static int lrotary_setup( lua_State* L )
DATA *d = data[id];
memset(d, 0, sizeof(*d));
d->id = id;
os_timer_setfn(&d->timer, lrotary_timer_done, (void *) d);
SWTIMER_REG_CB(lrotary_timer_done, SWTIMER_RESUME);
//lrotary_timer_done checks time elapsed since last event
//My guess: Since proper functionality relies on some variables to be reset via timer callback and state would be invalid anyway.
//It is probably best to resume this timer so it can reset it's state variables
int i;
for (i = 0; i < CALLBACK_COUNT; i++) {
......
......@@ -319,6 +319,7 @@ static void sntp_handle_result(lua_State *L) {
}
}
#include "pm/swtimer.h"
static void sntp_dosend ()
{
......@@ -326,6 +327,9 @@ static void sntp_dosend ()
if (state->server_pos < 0) {
os_timer_disarm(&state->timer);
os_timer_setfn(&state->timer, on_timeout, NULL);
SWTIMER_REG_CB(on_timeout, SWTIMER_RESUME);
//The function on_timeout calls this function(sntp_dosend) again to handle time sync timeout.
//My guess: Since the WiFi connection is restored after waking from light sleep, it would be possible to contact the SNTP server, So why not let it
state->server_pos = 0;
} else {
++state->server_pos;
......@@ -386,14 +390,13 @@ static void sntp_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
if (ipaddr == NULL)
{
sntp_dbg("DNS Fail!\n");
task_post_low(tasknumber, (uint32_t) name);
}
else
{
serverp[server_count] = *ipaddr;
server_count++;
task_post_low(tasknumber, SNTP_DOLOOKUPS_ID);
}
task_post_low(tasknumber, SNTP_DOLOOKUPS_ID);
}
......@@ -621,15 +624,26 @@ static void sntp_dolookups (lua_State *L) {
// at the end, start the lookups. If we have already looked everything up,
// then move straight to sending the packets.
if (state->list_ref == LUA_NOREF) {
sntp_dosend(L);
sntp_dosend();
return;
}
lua_rawgeti(L, LUA_REGISTRYINDEX, state->list_ref);
while (1) {
int l;
if (lua_objlen(L, -1) <= state->lookup_pos) {
// We reached the end
sntp_dosend(L);
if (server_count == 0) {
// Oh dear -- no valid entries -- generate an error
// This means that all the arguments are invalid. Just pick the first
lua_rawgeti(L, -1, 1);
const char *hostname = luaL_checklstring(L, -1, &l);
handle_error(L, NTP_DNS_ERR, hostname);
lua_pop(L, 1);
} else {
sntp_dosend();
}
break;
}
......@@ -637,8 +651,6 @@ static void sntp_dolookups (lua_State *L) {
lua_rawgeti(L, -1, state->lookup_pos);
int l;
const char *hostname = luaL_checklstring(L, -1, &l);
lua_pop(L, 1);
......@@ -700,6 +712,9 @@ static char *set_repeat_mode(lua_State *L, bool enable)
lua_rawgeti(L, LUA_REGISTRYINDEX, state->list_ref);
repeat->list_ref = luaL_ref(L, LUA_REGISTRYINDEX);
os_timer_setfn(&repeat->timer, on_long_timeout, NULL);
SWTIMER_REG_CB(on_long_timeout, SWTIMER_RESUME);
//The function on_long_timeout returns errors to the developer
//My guess: Error reporting is a good thing, resume the timer.
os_timer_arm(&repeat->timer, 1000 * 1000, 1);
} else {
if (repeat) {
......@@ -806,7 +821,7 @@ static int sntp_sync (lua_State *L)
goto good_ret;
}
sntp_dosend (L);
sntp_dosend ();
good_ret:
if (!lua_isnoneornil(L, 4)) {
......@@ -837,10 +852,8 @@ static void sntp_task(os_param_t param, uint8_t prio)
sntp_handle_result(L);
} else if (param == SNTP_DOLOOKUPS_ID) {
sntp_dolookups(L);
} else if (param >= 0 && param <= NTP_MAX_ERR_ID) {
handle_error(L, param, NULL);
} else {
handle_error(L, NTP_DNS_ERR, (const char *) param);
handle_error(L, param, NULL);
}
}
......
......@@ -15,6 +15,7 @@
#include "mem.h"
#include "lwip/ip_addr.h"
#include "espconn.h"
#include "sys/espconn_mbedtls.h"
#include "lwip/err.h"
#include "lwip/dns.h"
......
......@@ -53,7 +53,7 @@ tmr.softwd(int)
#include "platform.h"
#include "c_types.h"
#include "user_interface.h"
#include "swTimer/swTimer.h"
#include "pm/swtimer.h"
#define TIMER_MODE_OFF 3
#define TIMER_MODE_SINGLE 0
......@@ -128,9 +128,9 @@ 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 >= 10000){
us -= 10000;
os_delay_us(10000);
while(us >= 1000000){
us -= 1000000;
os_delay_us(1000000);
system_soft_wdt_feed ();
}
if(us>0){
......@@ -231,68 +231,23 @@ static int tmr_stop(lua_State* L){
return 1;
}
#ifdef ENABLE_TIMER_SUSPEND
#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){
timer_t tmr = tmr_get(L, 1);
if((tmr->mode & TIMER_IDLE_FLAG) == 1){
return luaL_error(L, "timer not armed");
}
int retval = swtmr_suspend(&tmr->os);
if(retval != SWTMR_OK){
return luaL_error(L, swtmr_errorcode2str(retval));
}
else{
lua_pushboolean(L, true);
}
return 1;
return luaL_error(L, TMR_SUSPEND_REMOVED_MSG);
}
static int tmr_resume(lua_State* L){
timer_t tmr = tmr_get(L, 1);
if(swtmr_suspended_test(&tmr->os) == FALSE){
return luaL_error(L, "timer not suspended");
}
int retval = swtmr_resume(&tmr->os);
if(retval != SWTMR_OK){
return luaL_error(L, swtmr_errorcode2str(retval));
}
else{
lua_pushboolean(L, true);
}
return 1;
return luaL_error(L, TMR_SUSPEND_REMOVED_MSG);
}
static int tmr_suspend_all (lua_State *L)
{
sint32 retval = swtmr_suspend(NULL);
// lua_pushnumber(L, swtmr_suspend(NULL));
if(retval!=SWTMR_OK){
return luaL_error(L, swtmr_errorcode2str(retval));
}
else{
lua_pushboolean(L, true);
}
return 1;
static int tmr_suspend_all (lua_State *L){
return luaL_error(L, TMR_SUSPEND_REMOVED_MSG);
}
static int tmr_resume_all (lua_State *L)
{
sint32 retval = swtmr_resume(NULL);
if(retval!=SWTMR_OK){
return luaL_error(L, swtmr_errorcode2str(retval));
}
else{
lua_pushboolean(L, true);
}
return 1;
static int tmr_resume_all (lua_State *L){
return luaL_error(L, TMR_SUSPEND_REMOVED_MSG);
}
......@@ -343,12 +298,7 @@ static int tmr_state(lua_State* L){
lua_pushboolean(L, (tmr->mode & TIMER_IDLE_FLAG) == 0);
lua_pushinteger(L, tmr->mode & (~TIMER_IDLE_FLAG));
#ifdef ENABLE_TIMER_SUSPEND
lua_pushboolean(L, swtmr_suspended_test(&tmr->os));
#else
lua_pushnil(L);
#endif
return 3;
return 2;
}
/*I left the led comments 'couse I don't know
......@@ -454,7 +404,7 @@ static const LUA_REG_TYPE tmr_dyn_map[] = {
{ LSTRKEY( "unregister" ), LFUNCVAL( tmr_unregister ) },
{ LSTRKEY( "state" ), LFUNCVAL( tmr_state ) },
{ LSTRKEY( "interval" ), LFUNCVAL( tmr_interval) },
#ifdef ENABLE_TIMER_SUSPEND
#ifdef TIMER_SUSPEND_ENABLE
{ LSTRKEY( "suspend" ), LFUNCVAL( tmr_suspend ) },
{ LSTRKEY( "resume" ), LFUNCVAL( tmr_resume ) },
#endif
......@@ -463,15 +413,6 @@ static const LUA_REG_TYPE tmr_dyn_map[] = {
{ LNILKEY, LNILVAL }
};
#if defined(ENABLE_TIMER_SUSPEND) && defined(SWTMR_DEBUG)
static const LUA_REG_TYPE tmr_dbg_map[] = {
{ LSTRKEY( "printRegistry" ), LFUNCVAL( tmr_printRegistry ) },
{ LSTRKEY( "printSuspended" ), LFUNCVAL( tmr_printSuspended ) },
{ LSTRKEY( "printTimerlist" ), LFUNCVAL( tmr_printTimerlist ) },
{ LNILKEY, LNILVAL }
};
#endif
static const LUA_REG_TYPE tmr_map[] = {
{ LSTRKEY( "delay" ), LFUNCVAL( tmr_delay ) },
{ LSTRKEY( "now" ), LFUNCVAL( tmr_now ) },
......@@ -482,7 +423,7 @@ static const LUA_REG_TYPE tmr_map[] = {
{ LSTRKEY( "alarm" ), LFUNCVAL( tmr_alarm ) },
{ LSTRKEY( "start" ), LFUNCVAL( tmr_start ) },
{ LSTRKEY( "stop" ), LFUNCVAL( tmr_stop ) },
#ifdef ENABLE_TIMER_SUSPEND
#ifdef TIMER_SUSPEND_ENABLE
{ LSTRKEY( "suspend" ), LFUNCVAL( tmr_suspend ) },
{ LSTRKEY( "suspend_all" ), LFUNCVAL( tmr_suspend_all ) },
{ LSTRKEY( "resume" ), LFUNCVAL( tmr_resume ) },
......@@ -492,15 +433,13 @@ static const LUA_REG_TYPE tmr_map[] = {
{ LSTRKEY( "state" ), LFUNCVAL( tmr_state ) },
{ LSTRKEY( "interval" ), LFUNCVAL( tmr_interval ) },
{ LSTRKEY( "create" ), LFUNCVAL( tmr_create ) },
#if defined(ENABLE_TIMER_SUSPEND) && defined(SWTMR_DEBUG)
{ LSTRKEY( "debug" ), LROVAL( tmr_dbg_map ) },
#endif
{ LSTRKEY( "ALARM_SINGLE" ), LNUMVAL( TIMER_MODE_SINGLE ) },
{ LSTRKEY( "ALARM_SEMI" ), LNUMVAL( TIMER_MODE_SEMI ) },
{ LSTRKEY( "ALARM_AUTO" ), LNUMVAL( TIMER_MODE_AUTO ) },
{ LNILKEY, LNILVAL }
};
#include "pm/swtimer.h"
int luaopen_tmr( lua_State *L ){
int i;
......@@ -510,16 +449,23 @@ int luaopen_tmr( lua_State *L ){
alarm_timers[i].lua_ref = LUA_NOREF;
alarm_timers[i].self_ref = LUA_REFNIL;
alarm_timers[i].mode = TIMER_MODE_OFF;
//improve boot speed by using ets_timer_disarm instead of os_timer_disarm to avoid timer registry maintenance call.
ets_timer_disarm(&alarm_timers[i].os);
os_timer_disarm(&alarm_timers[i].os);
}
last_rtc_time=system_get_rtc_time(); // Right now is time 0
last_rtc_time_us=0;
//improve boot speed by using ets_timer_disarm instead of os_timer_disarm to avoid timer registry maintenance call.
ets_timer_disarm(&rtc_timer);
os_timer_disarm(&rtc_timer);
os_timer_setfn(&rtc_timer, rtc_callback, NULL);
os_timer_arm(&rtc_timer, 1000, 1);
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'.
return 0;
}
......
......@@ -215,6 +215,124 @@ static int wifi_exit_smart( lua_State* L )
}
#endif // WIFI_SMART_ENABLE
// Lua: wifi.getcountry()
static int wifi_getcountry( lua_State* L ){
wifi_country_t cfg = {0};
if(wifi_get_country(&cfg)){
lua_newtable(L);
lua_pushstring(L, "country");
lua_pushstring(L, cfg.cc);
lua_rawset(L, -3);
lua_pushstring(L, "start_ch");
lua_pushnumber(L, cfg.schan);
lua_rawset(L, -3);
lua_pushstring(L, "end_ch");
lua_pushnumber(L, (cfg.schan + cfg.nchan)-1);
lua_rawset(L, -3);
lua_pushstring(L, "policy");
lua_pushnumber(L, cfg.policy);
lua_rawset(L, -3);
return 1;
}
else{
return luaL_error(L, "Unable to get country info");
}
}
// Lua: wifi.setcountry()
static int wifi_setcountry( lua_State* L ){
size_t len;
uint8 start_ch;
uint8 end_ch;
wifi_country_t cfg = {0};
if(lua_istable(L, 1)){
lua_getfield(L, 1, "country");
if (!lua_isnil(L, -1)){
if( lua_isstring(L, -1) ){
const char *country_code = luaL_checklstring( L, -1, &len );
luaL_argcheck(L, (len==2 && isalpha(country_code[0]) && isalpha(country_code[1])), 1, "country: country code must be 2 chars");
c_memcpy(cfg.cc, country_code, len);
if(cfg.cc[0] >= 0x61) cfg.cc[0]=cfg.cc[0]-32; //if lowercase change to uppercase
if(cfg.cc[1] >= 0x61) cfg.cc[1]=cfg.cc[1]-32; //if lowercase change to uppercase
}
else
return luaL_argerror( L, 1, "country: must be string" );
}
else{
cfg.cc[0]='C';
cfg.cc[1]='N';
cfg.cc[2]=0x00;
}
lua_pop(L, 1);
lua_getfield(L, 1, "start_ch");
if (!lua_isnil(L, -1)){
if(lua_isnumber(L, -1)){
start_ch = (uint8)luaL_checknumber(L, -1);
luaL_argcheck(L, (start_ch >= 1 && start_ch <= 14), 1, "start_ch: Range:1-14");
cfg.schan = start_ch;
}
else
luaL_argerror(L, 1, "start_ch: must be a number");
}
else
cfg.schan = 1;
lua_pop(L, 1);
lua_getfield(L, 1, "end_ch");
if (!lua_isnil(L, -1)){
if(lua_isnumber(L, -1)){
end_ch = (uint8)luaL_checknumber(L, -1);
luaL_argcheck(L, (end_ch >= 1 && end_ch <= 14), 1, "end_ch: Range:1-14");
luaL_argcheck(L, (end_ch >= cfg.schan), 1, "end_ch: can't be less than start_ch");
cfg.nchan = (end_ch-cfg.schan)+1; //cfg.nchan must equal total number of channels
}
else
luaL_argerror(L, 1, "end_ch: must be a number");
}
else
cfg.nchan = (13-cfg.schan)+1;
lua_pop(L, 1);
lua_getfield(L, 1, "policy");
if (!lua_isnil(L, -1)){
if(lua_isnumber(L, -1)){
uint8 policy = (uint8)luaL_checknumber(L, -1);
luaL_argcheck(L, (policy == WIFI_COUNTRY_POLICY_AUTO || policy == WIFI_COUNTRY_POLICY_MANUAL), 1, "policy: must be 0 or 1");
cfg.policy = policy;
}
else
luaL_argerror(L, 1, "policy: must be a number");
}
else
cfg.policy = WIFI_COUNTRY_POLICY_AUTO;
lua_pop(L, 1);
lua_pop(L, 1); //pop table from stack
bool retval = wifi_set_country(&cfg);
WIFI_DBG("\n country_cfg:\tcc:\"%s\"\tschan:%d\tnchan:%d\tpolicy:%d\n", cfg.cc, cfg.schan, cfg.nchan, cfg.policy);
if (retval==1)
lua_pushboolean(L, true);
else
return luaL_error(L, "Unable to set country info");
}
else
return luaL_argerror(L, 1, "Table not found!");
return 1;
}
// Lua: wifi.setmode(mode, save_to_flash)
static int wifi_setmode( lua_State* L )
{
......@@ -311,7 +429,7 @@ static int wifi_setmaxtxpower( lua_State* L )
#ifdef PMSLEEP_ENABLE
/* Begin WiFi suspend functions*/
#include "pmSleep.h"
#include <pm/pmSleep.h>
static int wifi_resume_cb_ref = LUA_NOREF; // Holds resume callback reference
static int wifi_suspend_cb_ref = LUA_NOREF; // Holds suspend callback reference
......@@ -393,6 +511,19 @@ static int wifi_resume(lua_State* L)
}
/* End WiFi suspend functions*/
#else
static char *susp_note_str = "\n The option \"pmsleep_enable\" in \"app/include/user_config.h\" was disabled during FW build!\n";
static char *susp_unavailable_str = "wifi.suspend is unavailable";
static int wifi_suspend(lua_State* L){
c_sprintf("%s", susp_note_str);
return luaL_error(L, susp_unavailable_str);
}
static int wifi_resume(lua_State* L){
c_sprintf("%s", susp_note_str);
return luaL_error(L, susp_unavailable_str);
}
#endif
// Lua: wifi.nullmodesleep()
......@@ -722,10 +853,7 @@ static int wifi_station_clear_config ( lua_State* L )
bool auto_connect=true;
bool save_to_flash=true;
memset(sta_conf.ssid, 0, sizeof(sta_conf.ssid));
memset(sta_conf.password, 0, sizeof(sta_conf.password));
memset(sta_conf.bssid, 0, sizeof(sta_conf.bssid));
sta_conf.bssid_set=0;
memset(&sta_conf, 0, sizeof(sta_conf));
wifi_station_disconnect();
......@@ -753,10 +881,9 @@ static int wifi_station_config( lua_State* L )
bool save_to_flash=true;
size_t sl, pl, ml;
memset(sta_conf.ssid, 0, sizeof(sta_conf.ssid));
memset(sta_conf.password, 0, sizeof(sta_conf.password));
memset(sta_conf.bssid, 0, sizeof(sta_conf.bssid));
sta_conf.bssid_set=0;
memset(&sta_conf, 0, sizeof(sta_conf));
sta_conf.threshold.rssi = -127;
sta_conf.threshold.authmode = AUTH_OPEN;
if(lua_istable(L, 1))
{
......@@ -849,7 +976,7 @@ static int wifi_station_config( lua_State* L )
lua_State* L_temp = NULL;
lua_getfield(L, 1, "connected_cb");
lua_getfield(L, 1, "connect_cb");
if (!lua_isnil(L, -1))
{
if (lua_isfunction(L, -1))
......@@ -862,12 +989,12 @@ static int wifi_station_config( lua_State* L )
}
else
{
return luaL_argerror(L, 1, "connected_cb:not function");
return luaL_argerror(L, 1, "connect_cb:not function");
}
}
lua_pop(L, 1);
lua_getfield(L, 1, "disconnected_cb");
lua_getfield(L, 1, "disconnect_cb");
if (!lua_isnil(L, -1))
{
if (lua_isfunction(L, -1))
......@@ -880,7 +1007,7 @@ static int wifi_station_config( lua_State* L )
}
else
{
return luaL_argerror(L, 1, "disconnected_cb:not function");
return luaL_argerror(L, 1, "disconnect_cb:not function");
}
}
lua_pop(L, 1);
......@@ -1032,6 +1159,8 @@ static int wifi_station_listap( lua_State* L )
return luaL_error( L, "Can't list ap in SOFTAP mode" );
}
struct scan_config scan_cfg;
memset(&scan_cfg, 0, sizeof(scan_cfg));
getap_output_format=0;
if (lua_type(L, 1)==LUA_TTABLE)
......@@ -1061,10 +1190,6 @@ static int wifi_station_listap( lua_State* L )
return luaL_error( L, "wrong arg type" );
}
}
else
{
scan_cfg.ssid=NULL;
}
lua_getfield(L, 1, "bssid");
if (!lua_isnil(L, -1)) /* found? */
......@@ -1085,10 +1210,6 @@ static int wifi_station_listap( lua_State* L )
return luaL_error( L, "wrong arg type" );
}
}
else
{
scan_cfg.bssid=NULL;
}
lua_getfield(L, 1, "channel");
......@@ -1107,10 +1228,6 @@ static int wifi_station_listap( lua_State* L )
return luaL_error( L, "wrong arg type" );
}
}
else
{
scan_cfg.channel=0;
}
lua_getfield(L, 1, "show_hidden");
if (!lua_isnil(L, -1)) /* found? */
......@@ -1129,10 +1246,6 @@ static int wifi_station_listap( lua_State* L )
return luaL_error( L, "wrong arg type" );
}
}
else
{
scan_cfg.show_hidden=0;
}
if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION)
{
......@@ -1805,13 +1918,13 @@ static const LUA_REG_TYPE wifi_map[] = {
{ LSTRKEY( "getmode" ), LFUNCVAL( wifi_getmode ) },
{ LSTRKEY( "getdefaultmode" ), LFUNCVAL( wifi_getdefaultmode ) },
{ LSTRKEY( "getchannel" ), LFUNCVAL( wifi_getchannel ) },
{ LSTRKEY( "getcountry" ), LFUNCVAL( wifi_getcountry ) },
{ LSTRKEY( "setcountry" ), LFUNCVAL( wifi_setcountry ) },
{ LSTRKEY( "setphymode" ), LFUNCVAL( wifi_setphymode ) },
{ LSTRKEY( "getphymode" ), LFUNCVAL( wifi_getphymode ) },
{ LSTRKEY( "setmaxtxpower" ), LFUNCVAL( wifi_setmaxtxpower ) },
#ifdef PMSLEEP_ENABLE
{ LSTRKEY( "suspend" ), LFUNCVAL( wifi_suspend ) },
{ LSTRKEY( "resume" ), LFUNCVAL( wifi_resume ) },
#endif
{ LSTRKEY( "nullmodesleep" ), LFUNCVAL( wifi_null_mode_auto_sleep ) },
#ifdef WIFI_SMART_ENABLE
{ LSTRKEY( "startsmart" ), LFUNCVAL( wifi_start_smart ) },
......@@ -1853,6 +1966,9 @@ static const LUA_REG_TYPE wifi_map[] = {
{ LSTRKEY( "STA_FAIL" ), LNUMVAL( STATION_CONNECT_FAIL ) },
{ LSTRKEY( "STA_GOTIP" ), LNUMVAL( STATION_GOT_IP ) },
{ LSTRKEY( "COUNTRY_AUTO" ), LNUMVAL( WIFI_COUNTRY_POLICY_AUTO ) },
{ LSTRKEY( "COUNTRY_MANUAL" ), LNUMVAL( WIFI_COUNTRY_POLICY_MANUAL ) },
{ LSTRKEY( "__metatable" ), LROVAL( wifi_map ) },
{ LNILKEY, LNILVAL }
};
......
......@@ -8,7 +8,7 @@
#include "user_interface.h"
#include "driver/uart.h"
#include "osapi.h"
#include "swTimer/swTimer.h"
#include "pm/swtimer.h"
#include "ws2812.h"
#include "color_utils.h"
......
......@@ -1056,6 +1056,7 @@ mdns_dup_info(const struct nodemcu_mdns_info *info) {
return result;
}
#include "pm/swtimer.h"
/**
* Initialize the resolver: set up the UDP pcb and configure the default server
* (NEW IP).
......@@ -1130,6 +1131,9 @@ nodemcu_mdns_init(struct nodemcu_mdns_info *info) {
//MDNS_DBG("About to start timer\n");
os_timer_disarm(&mdns_timer);
os_timer_setfn(&mdns_timer, (os_timer_func_t *)mdns_reg,ms_info);
SWTIMER_REG_CB(mdns_reg, SWTIMER_RESUME);
//the function mdns_reg registers the mdns device on the network
//My guess: Since wifi connection is restored after waking from light_sleep, the related timer would have no problem resuming it's normal function.
os_timer_arm(&mdns_timer, 1000 * 280, 1);
/* kick off the first one right away */
mdns_reg_handler_restart();
......
#include "pmSleep.h"
#include <pm/pmSleep.h>
#ifdef PMSLEEP_ENABLE
#define STRINGIFY_VAL(x) #x
#define STRINGIFY(x) STRINGIFY_VAL(x)
//TODO: figure out why timed light_sleep doesn't work
//holds duration error string
//uint32 PMSLEEP_SLEEP_MAX_TIME=FPM_SLEEP_MAX_TIME-1;
const char *PMSLEEP_DURATION_ERR_STR="duration: 0 or "STRINGIFY(PMSLEEP_SLEEP_MIN_TIME)"-"STRINGIFY(PMSLEEP_SLEEP_MAX_TIME)" us";
......@@ -28,17 +30,18 @@ static void wifi_suspended_timer_cb(int arg);
/* INTERNAL FUNCTIONS */
#include "swTimer/swTimer.h"
static void suspend_all_timers(void){
#ifdef ENABLE_TIMER_SUSPEND
swtmr_suspend(NULL);
#ifdef TIMER_SUSPEND_ENABLE
extern void swtmr_suspend_timers();
swtmr_suspend_timers();
#endif
return;
}
static void resume_all_timers(void){
#ifdef ENABLE_TIMER_SUSPEND
swtmr_resume(NULL);
#ifdef TIMER_SUSPEND_ENABLE
extern void swtmr_resume_timers();
swtmr_resume_timers();
#endif
return;
}
......@@ -49,7 +52,7 @@ static void null_mode_check_timer_cb(void* arg){
if(current_config.sleep_mode == LIGHT_SLEEP_T){
if((READ_PERI_REG(UART_STATUS(0)) & (UART_TXFIFO_CNT<<UART_TXFIFO_CNT_S)) == 0 &&
(READ_PERI_REG(UART_STATUS(1)) & (UART_TXFIFO_CNT<<UART_TXFIFO_CNT_S)) == 0){
ets_timer_disarm(&null_mode_check_timer);
os_timer_disarm(&null_mode_check_timer);
suspend_all_timers();
//Ensure UART 0/1 TX FIFO is clear
SET_PERI_REG_MASK(UART_CONF0(0), UART_TXFIFO_RST);//RESET FIFO
......@@ -71,6 +74,8 @@ static void null_mode_check_timer_cb(void* arg){
PMSLEEP_DBG("wifi_fpm_do_sleep success, starting wifi_suspend_test timer");
os_timer_disarm(&wifi_suspended_test_timer);
os_timer_setfn(&wifi_suspended_test_timer, (os_timer_func_t*)wifi_suspended_timer_cb, NULL);
//The callback wifi_suspended_timer_cb detects when the esp8266 has successfully entered modem_sleep and executes the developer's suspend_cb.
//Since this timer is only used in modem_sleep and will never be active outside of modem_sleep, it is unnecessary to register the cb with SWTIMER_REG_CB.
os_timer_arm(&wifi_suspended_test_timer, 1, 1);
}
else{ // This should never happen. if it does, return the value for error reporting
......@@ -78,7 +83,7 @@ static void null_mode_check_timer_cb(void* arg){
PMSLEEP_ERR("wifi_fpm_do_sleep returned %d", retval_wifi_fpm_do_sleep);
}
}
ets_timer_disarm(&null_mode_check_timer);
os_timer_disarm(&null_mode_check_timer);
return;
}
}
......@@ -173,24 +178,24 @@ uint8 pmSleep_get_state(void){
int pmSleep_parse_table_lua( lua_State* L, int table_idx, pmSleep_param_t *cfg, int *suspend_lua_cb_ref, int *resume_lua_cb_ref){
lua_Integer Linteger_tmp = 0;
lua_getfield(L, table_idx, "duration");
if( !lua_isnil(L, -1) ){ /* found? */
if( lua_isnumber(L, -1) ){
lua_Integer Linteger=luaL_checkinteger(L, -1);
luaL_argcheck(L,(((Linteger >= PMSLEEP_SLEEP_MIN_TIME) && (Linteger <= PMSLEEP_SLEEP_MAX_TIME)) ||
(Linteger == 0)), table_idx, PMSLEEP_DURATION_ERR_STR);
cfg->sleep_duration = (uint32)Linteger; // Get suspend duration
if( cfg->sleep_mode == MODEM_SLEEP_T ){ //WiFi suspend
lua_getfield(L, table_idx, "duration");
if( !lua_isnil(L, -1) ){ /* found? */
if( lua_isnumber(L, -1) ){
lua_Integer Linteger=luaL_checkinteger(L, -1);
luaL_argcheck(L,(((Linteger >= PMSLEEP_SLEEP_MIN_TIME) && (Linteger <= PMSLEEP_SLEEP_MAX_TIME)) ||
(Linteger == 0)), table_idx, PMSLEEP_DURATION_ERR_STR);
cfg->sleep_duration = (uint32)Linteger; // Get suspend duration
}
else{
return luaL_argerror( L, table_idx, "duration: must be number" );
}
}
else{
return luaL_argerror( L, table_idx, "duration: must be number" );
return luaL_argerror( L, table_idx, PMSLEEP_DURATION_ERR_STR );
}
}
else{
return luaL_argerror( L, table_idx, PMSLEEP_DURATION_ERR_STR );
}
lua_pop(L, 1);
lua_pop(L, 1);
if( cfg->sleep_mode == MODEM_SLEEP_T ){ //WiFi suspend
lua_getfield(L, table_idx, "suspend_cb");
if( !lua_isnil(L, -1) ){ /* found? */
if( lua_isfunction(L, -1) ){
......@@ -204,7 +209,7 @@ int pmSleep_parse_table_lua( lua_State* L, int table_idx, pmSleep_param_t *cfg,
lua_pop(L, 1);
}
else if (cfg->sleep_mode == LIGHT_SLEEP_T){ //CPU suspend
#ifdef ENABLE_TIMER_SUSPEND
#ifdef TIMER_SUSPEND_ENABLE
lua_getfield(L, table_idx, "wake_pin");
if( !lua_isnil(L, -1) ){ /* found? */
if( lua_isnumber(L, -1) ){
......@@ -216,9 +221,11 @@ int pmSleep_parse_table_lua( lua_State* L, int table_idx, pmSleep_param_t *cfg,
return luaL_argerror( L, table_idx, "wake_pin: must be number" );
}
}
else if(cfg->sleep_duration == 0){
return luaL_argerror( L, table_idx, "wake_pin: must specify pin if sleep duration is indefinite" );
}
else{
return luaL_argerror( L, table_idx, "wake_pin: must specify pin" );
// else if(cfg->sleep_duration == 0){
// return luaL_argerror( L, table_idx, "wake_pin: must specify pin if sleep duration is indefinite" );
}
lua_pop(L, 1);
lua_getfield(L, table_idx, "int_type");
......@@ -300,7 +307,7 @@ void pmSleep_suspend(pmSleep_param_t *cfg){
PMSLEEP_DBG("START");
lua_State* L = lua_getstate();
#ifndef ENABLE_TIMER_SUSPEND
#ifndef TIMER_SUSPEND_ENABLE
if(cfg->sleep_mode == LIGHT_SLEEP_T){
luaL_error(L, "timer suspend API is disabled, light sleep unavailable");
return;
......@@ -336,7 +343,7 @@ void pmSleep_suspend(pmSleep_param_t *cfg){
wifi_fpm_open(); // Enable force sleep API
if (cfg->sleep_mode == LIGHT_SLEEP_T){
#ifdef ENABLE_TIMER_SUSPEND
#ifdef TIMER_SUSPEND_ENABLE
if(platform_gpio_exists(cfg->wake_pin) && cfg->wake_pin > 0){
PMSLEEP_DBG("Wake-up pin is %d\t interrupt type is %d", cfg->wake_pin, cfg->int_type);
......@@ -366,10 +373,11 @@ void pmSleep_suspend(pmSleep_param_t *cfg){
c_memcpy(&current_config, cfg, sizeof(pmSleep_param_t));
PMSLEEP_DBG("sleep duration is %d", current_config.sleep_duration);
//this timer intentionally bypasses the swtimer timer registration process
ets_timer_disarm(&null_mode_check_timer);
ets_timer_setfn(&null_mode_check_timer, null_mode_check_timer_cb, false);
ets_timer_arm_new(&null_mode_check_timer, 1, 1, 1);
os_timer_disarm(&null_mode_check_timer);
os_timer_setfn(&null_mode_check_timer, null_mode_check_timer_cb, false);
//The function null_mode_check_timer_cb checks that the esp8266 has successfully changed the opmode to NULL_MODE prior to entering LIGHT_SLEEP
//This callback doesn't need to be registered with SWTIMER_REG_CB since the timer will have terminated before entering LIGHT_SLEEP
os_timer_arm(&null_mode_check_timer, 1, 1);
}
else{
PMSLEEP_ERR("opmode change fail");
......
/* swTimer.c SDK timer suspend API
*
* SDK software timer API info:
*
* The SDK software timer uses a linked list called `os_timer_t* timer_list` to keep track of
* all currently armed timers.
*
* The SDK software timer API executes in a task. The priority of this task in relation to the
* application level tasks is unknown (at time of writing).
*
*
* To determine when a timer's callback should be executed, the respective timer's `timer_expire`
* variable is compared to the hardware counter(FRC2), then, if the timer's `timer_expire` is
* less than the current FRC2 count, the timer's callback is fired.
*
* The timers in this list are organized in an ascending order starting with the timer
* with the lowest timer_expire.
*
* When a timer expires that has a timer_period greater than 0, timer_expire is changed to
* current FRC2 + timer_period, then the timer is inserted back in to the list in the correct position.
*
* when using millisecond(default) timers, FRC2 resolution is 312.5 ticks per millisecond.
*
*
* TIMER SUSPEND API INFO:
*
* Timer suspension is achieved by first finding any non-SDK timers by comparing the timer function callback pointer
* of each timer in "timer_list" to a list of registered timer callback pointers stored in the Lua registry.
* If a timer with a corresponding registered callback pointer is found, the timer's timer_expire field is is compared
* to the current FRC2 count and the difference is saved along with the other timer parameters to temporary variables.
* The timer is then disarmed and the parameters are copied back, the timer pointer is then
* added to a separate linked list of which the head pointer is stored as a lightuserdata in the lua registry.
*
* Resuming the timers is achieved by first retrieving the lightuserdata holding the suspended timer list head pointer.
* Then, starting with the beginning of the list the current FRC2 count is added back to the timer's timer_expire, then
* the timer is manually added back to "timer_list" in an ascending order.
* Once there are no more suspended timers, the function returns
*
*
*/#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "user_interface.h"
#include "user_modules.h"
#include "c_string.h"
#include "c_stdlib.h"
#include "ctype.h"
#include "c_types.h"
//#define SWTMR_DEBUG
#if !defined(SWTMR_DBG) && defined(LUA_USE_MODULES_SWTMR_DBG)
#define SWTMR_DEBUG
#endif
//this section specifies which lua registry to use. LUA_GLOBALSINDEX or LUA_REGISTRYINDEX
#ifdef SWTMR_DEBUG
#define SWTMR_DBG(fmt, ...) c_printf("\n SWTMR_DBG(%s): "fmt"\n", __FUNCTION__, ##__VA_ARGS__)
#define L_REGISTRY LUA_GLOBALSINDEX
#define CB_LIST_STR "timer_cb_ptrs"
#define SUSP_LIST_STR "suspended_tmr_LL_head"
#else
#define SWTMR_DBG(...)
#define L_REGISTRY LUA_REGISTRYINDEX
#define CB_LIST_STR "cb"
#define SUSP_LIST_STR "st"
#endif
typedef struct tmr_cb_queue{
os_timer_func_t *tmr_cb_ptr;
uint8 suspend_policy;
struct tmr_cb_queue * next;
}tmr_cb_queue_t;
typedef struct cb_registry_item{
os_timer_func_t *tmr_cb_ptr;
uint8 suspend_policy;
}cb_registry_item_t;
/* Internal variables */
static tmr_cb_queue_t* register_queue = NULL;
static task_handle_t cb_register_task_id = NULL; //variable to hold task id for task handler(process_cb_register_queue)
/* Function declarations */
//void swtmr_cb_register(void* timer_cb_ptr, uint8 resume_policy);
static void add_to_reg_queue(void* timer_cb_ptr, uint8 suspend_policy);
static void process_cb_register_queue(task_param_t param, uint8 priority);
#ifdef SWTMR_DEBUG
#define push_swtmr_registry_key(L) lua_pushstring(L, "SWTMR_registry_key")
#else
#define push_swtmr_registry_key(L) lua_pushlightuserdata(L, &register_queue);
#endif
#include <pm/swtimer.h>
void swtmr_suspend_timers(){
lua_State* L = lua_getstate();
//get swtimer table
push_swtmr_registry_key(L);
lua_rawget(L, L_REGISTRY);
//get cb_list table
lua_pushstring(L, CB_LIST_STR);
lua_rawget(L, -2);
//check for existence of the swtimer table and the cb_list table, return if not found
if(!lua_istable(L, -2) || !lua_istable(L, -1)){
// not necessarily an error maybe there are legitimately no timers to suspend
lua_pop(L, 2);
return;
}
os_timer_t* suspended_timer_list_head = NULL;
os_timer_t* suspended_timer_list_tail = NULL;
//get suspended_timer_list table
lua_pushstring(L, SUSP_LIST_STR);
lua_rawget(L, -3);
//if suspended_timer_list exists, find tail of list
if(lua_isuserdata(L, -1)){
suspended_timer_list_head = suspended_timer_list_tail = lua_touserdata(L, -1);
while(suspended_timer_list_tail->timer_next != NULL){
suspended_timer_list_tail = suspended_timer_list_tail->timer_next;
}
}
lua_pop(L, 1);
//get length of lua table containing the callback pointers
size_t registered_cb_qty = lua_objlen(L, -1);
//allocate a temporary array to hold the list of callback pointers
cb_registry_item_t** cb_reg_array = c_zalloc(sizeof(cb_registry_item_t*)*registered_cb_qty);
if(!cb_reg_array){
luaL_error(L, "%s: unable to suspend timers, out of memory!", __func__);
return;
}
uint8 index = 0;
//convert lua table cb_list to c array
lua_pushnil(L);
while(lua_next(L, -2) != 0){
if(lua_isuserdata(L, -1)){
cb_reg_array[index] = lua_touserdata(L, -1);
}
lua_pop(L, 1);
index++;
}
//the cb_list table is no longer needed, pop it from the stack
lua_pop(L, 1);
volatile uint32 frc2_count = RTC_REG_READ(FRC2_COUNT_ADDRESS);
os_timer_t* timer_ptr = timer_list;
uint32 expire_temp = 0;
uint32 period_temp = 0;
void* arg_temp = NULL;
/* In this section, the SDK's timer_list is traversed to find any timers that have a registered callback pointer.
* If a registered callback is found, the timer is suspended by saving the difference
* between frc2_count and timer_expire then the timer is disarmed and placed into suspended_timer_list
* so it can later be resumed.
*/
while(timer_ptr != NULL){
os_timer_t* next_timer = (os_timer_t*)0xffffffff;
for(int i = 0; i < registered_cb_qty; i++){
if(timer_ptr->timer_func == cb_reg_array[i]->tmr_cb_ptr){
//current timer will be suspended, next timer's pointer will be needed to continue processing timer_list
next_timer = timer_ptr->timer_next;
//store timer parameters temporarily so the timer can be disarmed
if(timer_ptr->timer_expire < frc2_count)
expire_temp = 2; // 16 us in ticks (1 tick = ~3.2 us) (arbitrarily chosen value)
else
expire_temp = timer_ptr->timer_expire - frc2_count;
period_temp = timer_ptr->timer_period;
arg_temp = timer_ptr->timer_arg;
if(timer_ptr->timer_period == 0 && cb_reg_array[i]->suspend_policy == SWTIMER_RESTART){
SWTMR_DBG("Warning: suspend_policy(RESTART) is not compatible with single-shot timer(%p), changing suspend_policy to (RESUME)", timer_ptr);
cb_reg_array[i]->suspend_policy = SWTIMER_RESUME;
}
//remove the timer from timer_list so we don't have to.
os_timer_disarm(timer_ptr);
timer_ptr->timer_next = NULL;
//this section determines timer behavior on resume
if(cb_reg_array[i]->suspend_policy == SWTIMER_DROP){
SWTMR_DBG("timer(%p) was disarmed and will not be resumed", timer_ptr);
}
else if(cb_reg_array[i]->suspend_policy == SWTIMER_IMMEDIATE){
timer_ptr->timer_expire = 1;
SWTMR_DBG("timer(%p) will fire immediately on resume", timer_ptr);
}
else if(cb_reg_array[i]->suspend_policy == SWTIMER_RESTART){
timer_ptr->timer_expire = period_temp;
SWTMR_DBG("timer(%p) will be restarted on resume", timer_ptr);
}
else{
timer_ptr->timer_expire = expire_temp;
SWTMR_DBG("timer(%p) will be resumed with remaining time", timer_ptr);
}
if(cb_reg_array[i]->suspend_policy != SWTIMER_DROP){
timer_ptr->timer_period = period_temp;
timer_ptr->timer_func = cb_reg_array[i]->tmr_cb_ptr;
timer_ptr->timer_arg = arg_temp;
//add timer to suspended_timer_list
if(suspended_timer_list_head == NULL){
suspended_timer_list_head = timer_ptr;
suspended_timer_list_tail = timer_ptr;
}
else{
suspended_timer_list_tail->timer_next = timer_ptr;
suspended_timer_list_tail = timer_ptr;
}
}
}
}
//if timer was suspended, timer_ptr->timer_next is invalid, use next_timer instead.
if(next_timer != (os_timer_t*)0xffffffff){
timer_ptr = next_timer;
}
else{
timer_ptr = timer_ptr->timer_next;
}
}
//tmr_cb_ptr_array is no longer needed.
c_free(cb_reg_array);
//add suspended_timer_list pointer to swtimer table.
lua_pushstring(L, SUSP_LIST_STR);
lua_pushlightuserdata(L, suspended_timer_list_head);
lua_rawset(L, -3);
//pop swtimer table from stack
lua_pop(L, 1);
return;
}
void swtmr_resume_timers(){
lua_State* L = lua_getstate();
//get swtimer table
push_swtmr_registry_key(L);
lua_rawget(L, L_REGISTRY);
//get suspended_timer_list lightuserdata
lua_pushstring(L, SUSP_LIST_STR);
lua_rawget(L, -2);
//check for existence of swtimer table and the suspended_timer_list pointer userdata, return if not found
if(!lua_istable(L, -2) || !lua_isuserdata(L, -1)){
// not necessarily an error maybe there are legitimately no timers to resume
lua_pop(L, 2);
return;
}
os_timer_t* suspended_timer_list_ptr = lua_touserdata(L, -1);
lua_pop(L, 1); //pop suspended timer list userdata from stack
//since timers will be resumed, the suspended_timer_list lightuserdata can be cleared from swtimer table
lua_pushstring(L, SUSP_LIST_STR);
lua_pushnil(L);
lua_rawset(L, -3);
lua_pop(L, 1); //pop swtimer table from stack
volatile uint32 frc2_count = RTC_REG_READ(FRC2_COUNT_ADDRESS);
//this section does the actual resuming of the suspended timer(s)
while(suspended_timer_list_ptr != NULL){
os_timer_t* timer_list_ptr = timer_list;
//the pointer to next suspended timer must be saved, the current suspended timer will be removed from the list
os_timer_t* next_suspended_timer_ptr = suspended_timer_list_ptr->timer_next;
suspended_timer_list_ptr->timer_expire += frc2_count;
//traverse timer_list to determine where to insert suspended timer
while(timer_list_ptr != NULL){
if(suspended_timer_list_ptr->timer_expire > timer_list_ptr->timer_expire){
if(timer_list_ptr->timer_next != NULL){
//current timer is not at tail of timer_list
if(suspended_timer_list_ptr->timer_expire < timer_list_ptr->timer_next->timer_expire){
//insert suspended timer between current timer and next timer
suspended_timer_list_ptr->timer_next = timer_list_ptr->timer_next;
timer_list_ptr->timer_next = suspended_timer_list_ptr;
break; //timer resumed exit while loop
}
else{
//suspended timer expire is larger than next timer
}
}
else{
//current timer is at tail of timer_list and suspended timer expire is greater then current timer
//append timer to end of timer_list
timer_list_ptr->timer_next = suspended_timer_list_ptr;
suspended_timer_list_ptr->timer_next = NULL;
break; //timer resumed exit while loop
}
}
else if(timer_list_ptr == timer_list){
//insert timer at head of list
suspended_timer_list_ptr->timer_next = timer_list_ptr;
timer_list = timer_list_ptr = suspended_timer_list_ptr;
break; //timer resumed exit while loop
}
//suspended timer expire is larger than next timer
//timer not resumed, next timer in timer_list
timer_list_ptr = timer_list_ptr->timer_next;
}
//timer was resumed, next suspended timer
suspended_timer_list_ptr = next_suspended_timer_ptr;
}
return;
}
//this function registers a timer callback pointer in a lua table
void swtmr_cb_register(void* timer_cb_ptr, uint8 suspend_policy){
lua_State* L = lua_getstate();
if(!L){
//Lua has not started yet, therefore L_REGISTRY is not available.
//add timer cb to queue for later processing after Lua has started
add_to_reg_queue(timer_cb_ptr, suspend_policy);
return;
}
if(timer_cb_ptr){
size_t cb_list_last_idx = 0;
push_swtmr_registry_key(L);
lua_rawget(L, L_REGISTRY);
if(!lua_istable(L, -1)){
//swtmr does not exist, create and add to registry
lua_pop(L, 1);
lua_newtable(L);//push new table for swtmr.timer_cb_list
// add swtimer table to L_REGISTRY
push_swtmr_registry_key(L);
lua_pushvalue(L, -2);
lua_rawset(L, L_REGISTRY);
}
lua_pushstring(L, CB_LIST_STR);
lua_rawget(L, -2);
if(lua_istable(L, -1)){
//cb_list exists, get length of list
cb_list_last_idx = lua_objlen(L, -1);
}
else{
//cb_list does not exist in swtmr, create and add to swtmr
lua_pop(L, 1);// pop nil value from stack
lua_newtable(L);//create new table for swtmr.timer_cb_list
lua_pushstring(L, CB_LIST_STR); //push name for the new table onto the stack
lua_pushvalue(L, -2); //push table to top of stack
lua_rawset(L, -4); //pop table and name from stack and register in swtmr
}
//append new timer cb ptr to table
lua_pushnumber(L, cb_list_last_idx+1);
cb_registry_item_t* reg_item = lua_newuserdata(L, sizeof(cb_registry_item_t));
reg_item->tmr_cb_ptr = timer_cb_ptr;
reg_item->suspend_policy = suspend_policy;
lua_rawset(L, -3);
//clear items pushed onto stack by this function
lua_pop(L, 2);
}
return;
}
//this function adds the timer cb ptr to a queue for later registration after lua has started
static void add_to_reg_queue(void* timer_cb_ptr, uint8 suspend_policy){
if(!timer_cb_ptr)
return;
tmr_cb_queue_t* queue_temp = c_zalloc(sizeof(tmr_cb_queue_t));
if(!queue_temp){
//it's boot time currently and we're already out of memory, something is very wrong...
c_printf("\n\t%s:out of memory, system halted!\n", __FUNCTION__);
while(1)
system_soft_wdt_feed();
}
queue_temp->tmr_cb_ptr = timer_cb_ptr;
queue_temp->suspend_policy = suspend_policy;
queue_temp->next = NULL;
if(register_queue == NULL){
register_queue = queue_temp;
}
else{
tmr_cb_queue_t* queue_ptr = register_queue;
while(queue_ptr->next != NULL){
queue_ptr = queue_ptr->next;
}
queue_ptr->next = queue_temp;
}
if(!cb_register_task_id){
cb_register_task_id = task_get_id(process_cb_register_queue);//get task id from task interface
task_post_low(cb_register_task_id, false); //post task to process next item in queue
}
return;
}
static void process_cb_register_queue(task_param_t param, uint8 priority)
{
if(!lua_getstate()){
SWTMR_DBG("L== NULL, Lua not yet started! posting task");
task_post_low(cb_register_task_id, false); //post task to process next item in queue
return;
}
while(register_queue != NULL){
tmr_cb_queue_t* register_queue_ptr = register_queue;
void* cb_ptr_tmp = register_queue_ptr->tmr_cb_ptr;
swtmr_cb_register(cb_ptr_tmp, register_queue_ptr->suspend_policy);
register_queue = register_queue->next;
c_free(register_queue_ptr);
}
return;
}
#ifdef SWTMR_DEBUG
int print_timer_list(lua_State* L){
push_swtmr_registry_key(L);
lua_rawget(L, L_REGISTRY);
lua_pushstring(L, CB_LIST_STR);
lua_rawget(L, -2);
if(!lua_istable(L, -2) || !lua_istable(L, -1)){
lua_pop(L, 2);
return 0;
}
os_timer_t* suspended_timer_list_head = NULL;
os_timer_t* suspended_timer_list_tail = NULL;
lua_pushstring(L, SUSP_LIST_STR);
lua_rawget(L, -3);
if(lua_isuserdata(L, -1)){
suspended_timer_list_head = suspended_timer_list_tail = lua_touserdata(L, -1);
while(suspended_timer_list_tail->timer_next != NULL){
suspended_timer_list_tail = suspended_timer_list_tail->timer_next;
}
}
lua_pop(L, 1);
size_t registered_cb_qty = lua_objlen(L, -1);
cb_registry_item_t** cb_reg_array = c_zalloc(sizeof(cb_registry_item_t*)*registered_cb_qty);
if(!cb_reg_array){
luaL_error(L, "%s: unable to suspend timers, out of memory!", __func__);
return 0;
}
uint8 index = 0;
lua_pushnil(L);
while(lua_next(L, -2) != 0){
if(lua_isuserdata(L, -1)){
cb_reg_array[index] = lua_touserdata(L, -1);
}
lua_pop(L, 1);
index++;
}
lua_pop(L, 1);
os_timer_t* timer_list_ptr = timer_list;
c_printf("\n\tCurrent FRC2: %u\n", RTC_REG_READ(FRC2_COUNT_ADDRESS));
c_printf("\ttimer_list:\n");
while(timer_list_ptr != NULL){
bool registered_flag = FALSE;
for(int i=0; i < registered_cb_qty; i++){
if(timer_list_ptr->timer_func == cb_reg_array[i]->tmr_cb_ptr){
registered_flag = TRUE;
break;
}
}
c_printf("\tptr:%p\tcb:%p\texpire:%8u\tperiod:%8u\tnext:%p\t%s\n",
timer_list_ptr, timer_list_ptr->timer_func, timer_list_ptr->timer_expire, timer_list_ptr->timer_period, timer_list_ptr->timer_next, registered_flag ? "Registered" : "");
timer_list_ptr = timer_list_ptr->timer_next;
}
c_free(cb_reg_array);
lua_pop(L, 1);
return 0;
}
int print_susp_timer_list(lua_State* L){
push_swtmr_registry_key(L);
lua_rawget(L, L_REGISTRY);
if(!lua_istable(L, -1)){
return luaL_error(L, "swtmr table not found!");
}
lua_pushstring(L, SUSP_LIST_STR);
lua_rawget(L, -2);
if(!lua_isuserdata(L, -1)){
return luaL_error(L, "swtmr.suspended_list userdata not found!");
}
os_timer_t* susp_timer_list_ptr = lua_touserdata(L, -1);
c_printf("\n\tsuspended_timer_list:\n");
while(susp_timer_list_ptr != NULL){
c_printf("\tptr:%p\tcb:%p\texpire:%8u\tperiod:%8u\tnext:%p\n",susp_timer_list_ptr, susp_timer_list_ptr->timer_func, susp_timer_list_ptr->timer_expire, susp_timer_list_ptr->timer_period, susp_timer_list_ptr->timer_next);
susp_timer_list_ptr = susp_timer_list_ptr->timer_next;
}
return 0;
}
int suspend_timers_lua(lua_State* L){
swtmr_suspend_timers();
return 0;
}
int resume_timers_lua(lua_State* L){
swtmr_resume_timers();
return 0;
}
static const LUA_REG_TYPE test_swtimer_debug_map[] = {
{ LSTRKEY( "timer_list" ), LFUNCVAL( print_timer_list ) },
{ LSTRKEY( "susp_timer_list" ), LFUNCVAL( print_susp_timer_list ) },
{ LSTRKEY( "suspend" ), LFUNCVAL( suspend_timers_lua ) },
{ LSTRKEY( "resume" ), LFUNCVAL( resume_timers_lua ) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(SWTMR_DBG, "SWTMR_DBG", test_swtimer_debug_map, NULL);
#endif
......@@ -3,6 +3,7 @@
#include "c_string.h"
#include "user_interface.h"
#include "smart.h"
#include "pm/swtimer.h"
#define ADDR_MAP_NUM 10
......@@ -500,6 +501,9 @@ void smart_end(){
os_timer_disarm(&smart_timer);
os_timer_setfn(&smart_timer, (os_timer_func_t *)station_check_connect, (void *)1);
SWTIMER_REG_CB(station_check_connect, SWTIMER_RESUME);
//the function station_check_connect continues the Smart config process and fires the developers callback upon successful connection to the access point.
//If this function manages to get suspended, I think it would be fine to resume the timer.
os_timer_arm(&smart_timer, STATION_CHECK_TIME, 0); // no repeat
}
}
......@@ -672,6 +676,9 @@ void smart_begin(int chnl, smart_succeed s, void *arg){
wifi_set_promiscuous_rx_cb(detect);
os_timer_disarm(&smart_timer);
os_timer_setfn(&smart_timer, (os_timer_func_t *)smart_next_channel, NULL);
SWTIMER_REG_CB(smart_next_channel, SWTIMER_RESUME);
//smart_next_channel switches the wifi channel
//I don't see a problem with resuming this timer
os_timer_arm(&smart_timer, TIME_OUT_PER_CHANNEL, 0); // no repeat
if(s){
......@@ -717,5 +724,6 @@ void station_check_connect(bool smart){
}
os_timer_disarm(&smart_timer);
os_timer_setfn(&smart_timer, (os_timer_func_t *)station_check_connect, (void *)(int)smart);
//this function was already registered in the function smart_end.
os_timer_arm(&smart_timer, STATION_CHECK_TIME, 0); // no repeat
}
......@@ -576,8 +576,11 @@ static int esp8266_Sleep( sqlite3_vfs * vfs, int microseconds )
static int esp8266_CurrentTime( sqlite3_vfs * vfs, double * result )
{
time_t t = time(NULL);
*result = t / 86400.0 + 2440587.5;
// This is stubbed out until we have a working RTCTIME solution;
// as it stood, this would always have returned the UNIX epoch.
// time_t t = time(NULL);
// *result = t / 86400.0 + 2440587.5;
*result = 2440587.5;
dbg_printf("esp8266_CurrentTime: %g\n", *result);
return SQLITE_OK;
}
......
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libswtimer.a
endif
STD_CFLAGS=-std=gnu11 -Wimplicit
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./
INCLUDES += -I ./include
INCLUDES += -I ../include
INCLUDES += -I ../../include
INCLUDES += -I ../lua
INCLUDES += -I ../platform
INCLUDES += -I ../libc
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
/* swTimer.c SDK timer suspend API
*
* SDK software timer API info:
*
* The SDK software timer uses a linked list called `os_timer_t* timer_list` to keep track of
* all currently armed timers.
*
* The SDK software timer API executes in a task. The priority of this task in relation to the
* application level tasks is unknown (at time of writing).
*
*
* To determine when a timer's callback should be executed, the respective timer's `timer_expire`
* variable is compared to the hardware counter(FRC2), then, if the timer's `timer_expire` is
* less than the current FRC2 count, the timer's callback is fired.
*
* The timers in this list are organized in an ascending order starting with the timer
* with the lowest timer_expire.
*
* When a timer expires that has a timer_period greater than 0, timer_expire is changed to
* current FRC2 + timer_period, then the timer is inserted back in to the list in the correct position.
*
* when using millisecond(default) timers, FRC2 resolution is 312.5 ticks per millisecond.
*
*
* TIMER SUSPEND API:
*
* Timer registry:
* void sw_timer_register(void* timer_ptr);
* - Adds timers to the timer registry by adding it to a queue that is later
* processed by timer_register_task that performs the registry maintenance
*
* void sw_timer_unregister(void* timer_ptr);
* - Removes timers from the timer registry by adding it to a queue that is later
* processed by timer_unregister_task that performs the registry maintenance
*
*
* int sw_timer_suspend(os_timer_t* timer_ptr);
* - Suspend a single active timer or suspend all active timers.
* - if no timer pointer is provided, timer_ptr == NULL, then all currently active timers will be suspended.
*
* int sw_timer_resume(os_timer_t* timer_ptr);
* - Resume a single suspended timer or resume all suspended timers.
* - if no timer pointer is provided, timer_ptr == NULL, then all currently suspended timers will be resumed.
*
*
*
*/
#include "swTimer/swTimer.h"
#include "c_stdio.h"
#include "misc/dynarr.h"
#include "task/task.h"
#ifdef ENABLE_TIMER_SUSPEND
/* Settings */
#define TIMER_REGISTRY_INITIAL_SIZE 10
#ifdef USE_SWTMR_ERROR_STRINGS
static const char* SWTMR_ERROR_STRINGS[]={
[SWTMR_MALLOC_FAIL] = "Out of memory!",
[SWTMR_TIMER_NOT_ARMED] = "Timer is not armed",
// [SWTMR_NULL_PTR] = "A NULL pointer was passed to timer suspend api",
[SWTMR_REGISTRY_NO_REGISTERED_TIMERS] = "No timers in registry",
// [SWTMR_SUSPEND_ARRAY_INITIALIZATION_FAILED] = "Suspend array init fail",
// [SWTMR_SUSPEND_ARRAY_ADD_FAILED] = "Unable to add suspended timer to array",
// [SWTMR_SUSPEND_ARRAY_REMOVE_FAILED] = "Unable to remove suspended timer from array",
[SWTMR_SUSPEND_TIMER_ALREADY_SUSPENDED] = "Already suspended",
[SWTMR_SUSPEND_TIMER_ALREADY_REARMED] = "Already been re-armed",
[SWTMR_SUSPEND_NO_SUSPENDED_TIMERS] = "No suspended timers",
[SWTMR_SUSPEND_TIMER_NOT_SUSPENDED] = "Not suspended",
};
#endif
/* Private Function Declarations */
static inline bool timer_armed_check(os_timer_t* timer_ptr);
static inline int timer_do_suspend(os_timer_t* timer_ptr);
static inline int timer_do_resume_single(os_timer_t** suspended_timer_ptr);
static void timer_register_task(task_param_t param, uint8 priority);
static inline os_timer_t** timer_registry_check(os_timer_t* timer_ptr);
static inline void timer_registry_remove_unarmed(void);
static inline os_timer_t** timer_suspended_check(os_timer_t* timer_ptr);
static void timer_unregister_task(task_param_t param, uint8 priority);
/* Private Variable Definitions */
static task_handle_t timer_reg_task_id = false;
static task_handle_t timer_unreg_task_id = false;
static dynarr_t timer_registry = {0};
static dynarr_t suspended_timers = {0};
typedef struct registry_queue{
struct registry_queue* next;
os_timer_t* timer_ptr;
}registry_queue_t;
static registry_queue_t* register_queue = NULL;
static registry_queue_t* unregister_queue = NULL;
/* Private Function Definitions */
//NOTE: Interrupts are temporarily blocked during the execution of this function
static inline bool timer_armed_check(os_timer_t* timer_ptr){
bool retval = FALSE;
// we are messing around with the SDK timer structure here, may not be necessary, better safe than sorry though.
ETS_INTR_LOCK();
os_timer_t* timer_list_ptr = timer_list; //get head node pointer of timer_list
//if present find timer_ptr in timer_list rand return result
while(timer_list_ptr != NULL){
if(timer_list_ptr == timer_ptr){
retval = TRUE;
break;
}
timer_list_ptr = timer_list_ptr->timer_next;
}
//we are done with timer_list, it is now safe to unlock interrupts
ETS_INTR_UNLOCK();
//return value
return retval;
}
static inline int timer_do_suspend(os_timer_t* timer_ptr){
if(timer_ptr == NULL){
SWTMR_ERR("timer_ptr is invalid");
return SWTMR_FAIL;
}
volatile uint32 frc2_count = RTC_REG_READ(FRC2_COUNT_ADDRESS);
if(timer_armed_check(timer_ptr) == FALSE){
return SWTMR_TIMER_NOT_ARMED;
}
os_timer_t** suspended_timer_ptr = timer_suspended_check(timer_ptr);
uint32 expire_temp = 0;
uint32 period_temp = timer_ptr->timer_period;
if(timer_ptr->timer_expire < frc2_count){
expire_temp = 5; // 16 us in ticks (1 tick = ~3.2 us) (arbitrarily chosen value)
}
else{
expire_temp = timer_ptr->timer_expire - frc2_count;
}
ets_timer_disarm(timer_ptr);
timer_unregister_task((task_param_t)timer_ptr, false);
timer_ptr->timer_expire = expire_temp;
timer_ptr->timer_period = period_temp;
if(suspended_timers.data_ptr == NULL){
if(!dynarr_init(&suspended_timers, 10, sizeof(os_timer_t*))){
SWTMR_ERR("Suspend array init fail");
return SWTMR_FAIL;
}
}
if(suspended_timer_ptr == NULL){
// return SWTMR_SUSPEND_TIMER_ALREADY_SUSPENDED;
if(!dynarr_add(&suspended_timers, &timer_ptr, sizeof(timer_ptr))){
SWTMR_ERR("Unable to add suspended timer to array");
return SWTMR_FAIL;
}
}
return SWTMR_OK;
}
//NOTE: Interrupts are temporarily blocked during the execution of this function
static inline int timer_do_resume_single(os_timer_t** suspended_timer_ptr){
if(suspended_timer_ptr == NULL){
SWTMR_ERR("suspended_timer_ptr is invalid");
return SWTMR_FAIL;
}
os_timer_t* timer_list_ptr = NULL;
os_timer_t* resume_timer_ptr = *suspended_timer_ptr;
volatile uint32 frc2_count = RTC_REG_READ(FRC2_COUNT_ADDRESS);
//verify timer has not been rearmed
if(timer_armed_check(resume_timer_ptr) == TRUE){
SWTMR_DBG("Timer(%p) already rearmed, removing from array", resume_timer_ptr);
if(!dynarr_remove(&suspended_timers, suspended_timer_ptr)){
SWTMR_ERR("Failed to remove timer from suspend array");
return SWTMR_FAIL;
}
return SWTMR_OK;
}
//Prepare timer for resume
resume_timer_ptr->timer_expire += frc2_count;
timer_register_task((task_param_t)resume_timer_ptr, false);
SWTMR_DBG("Removing timer(%p) from suspend array", resume_timer_ptr);
//This section performs the actual resume of the suspended timer
// we are messing around with the SDK timer structure here, may not be necessary, better safe than sorry though.
ETS_INTR_LOCK();
timer_list_ptr = timer_list;
while(timer_list_ptr != NULL){
if(resume_timer_ptr->timer_expire > timer_list_ptr->timer_expire){
if(timer_list_ptr->timer_next != NULL){
if(resume_timer_ptr->timer_expire < timer_list_ptr->timer_next->timer_expire){
resume_timer_ptr->timer_next = timer_list_ptr->timer_next;
timer_list_ptr->timer_next = resume_timer_ptr;
break;
}
else{
//next timer in timer_list
}
}
else{
timer_list_ptr->timer_next = resume_timer_ptr;
resume_timer_ptr->timer_next = NULL;
break;
}
}
else if(timer_list_ptr == timer_list){
resume_timer_ptr->timer_next=timer_list_ptr;
timer_list = timer_list_ptr = resume_timer_ptr;
break;
}
timer_list_ptr = timer_list_ptr->timer_next;
}
//we no longer need to block interrupts
ETS_INTR_UNLOCK();
return SWTMR_OK;
}
static void timer_register_task(task_param_t param, uint8 priority){
if(timer_registry.data_ptr==NULL){
if(!dynarr_init(&timer_registry, TIMER_REGISTRY_INITIAL_SIZE, sizeof(os_timer_t*))){
SWTMR_ERR("timer registry init Fail!");
return;
}
}
os_timer_t* timer_ptr = NULL;
//if a timer pointer is provided, override normal queue processing behavior
if(param != 0){
timer_ptr = (os_timer_t*)param;
}
else{
//process an item in the register queue
if(register_queue == NULL){
/**/SWTMR_ERR("ERROR: REGISTER QUEUE EMPTY");
return;
}
registry_queue_t* queue_temp = register_queue;
register_queue = register_queue->next;
timer_ptr = queue_temp->timer_ptr;
c_free(queue_temp);
if(register_queue != NULL){
SWTMR_DBG("register_queue not empty, posting task");
task_post_low(timer_reg_task_id, false);
}
}
os_timer_t** suspended_tmr_ptr = timer_suspended_check(timer_ptr);
if(suspended_tmr_ptr != NULL){
if(!dynarr_remove(&suspended_timers, suspended_tmr_ptr)){
SWTMR_ERR("failed to remove %p from suspend registry", suspended_tmr_ptr);
}
SWTMR_DBG("removed timer from suspended timers");
}
if(timer_registry_check(timer_ptr) != NULL){
/**/SWTMR_DBG("timer(%p) found in registry, returning", timer_ptr);
return;
}
if(!dynarr_add(&timer_registry, &timer_ptr, sizeof(timer_ptr))){
/**/SWTMR_ERR("Registry append failed");
return;
}
return;
}
static inline os_timer_t** timer_registry_check(os_timer_t* timer_ptr){
if(timer_registry.data_ptr == NULL){
return NULL;
}
if(timer_registry.used > 0){
os_timer_t** timer_registry_array = timer_registry.data_ptr;
for(uint32 i=0; i < timer_registry.used; i++){
if(timer_registry_array[i] == timer_ptr){
/**/SWTMR_DBG("timer(%p) is registered", timer_registry_array[i]);
return &timer_registry_array[i];
}
}
}
return NULL;
}
static inline void timer_registry_remove_unarmed(void){
if(timer_registry.data_ptr == NULL){
return;
}
if(timer_registry.used > 0){
os_timer_t** timer_registry_array = timer_registry.data_ptr;
for(uint32 i=0; i < timer_registry.used; i++){
if(timer_armed_check(timer_registry_array[i]) == FALSE){
timer_unregister_task((task_param_t)timer_registry_array[i], false);
}
}
}
}
static inline os_timer_t** timer_suspended_check(os_timer_t* timer_ptr){
if(suspended_timers.data_ptr == NULL){
return NULL;
}
if(suspended_timers.used > 0){
os_timer_t** suspended_timer_array = suspended_timers.data_ptr;
for(uint32 i=0; i < suspended_timers.used; i++){
if(suspended_timer_array[i] == timer_ptr){
return &suspended_timer_array[i];
}
}
}
return NULL;
}
static void timer_unregister_task(task_param_t param, uint8 priority){
if(timer_registry.data_ptr == NULL){
return;
}
os_timer_t* timer_ptr = NULL;
if(param != false){
timer_ptr = (os_timer_t*)param;
}
else{
if(unregister_queue == NULL) {
SWTMR_ERR("ERROR register queue empty");
return;
}
registry_queue_t* queue_temp = unregister_queue;
timer_ptr = queue_temp->timer_ptr;
unregister_queue = unregister_queue->next;
c_free(queue_temp);
if(unregister_queue != NULL){
SWTMR_DBG("unregister_queue not empty, posting task");
task_post_low(timer_unreg_task_id, false);
}
}
if(timer_armed_check(timer_ptr) == TRUE){
SWTMR_DBG("%p still armed, can't remove from registry", timer_ptr);
return;
}
os_timer_t** registry_ptr = timer_registry_check(timer_ptr);
if(registry_ptr != NULL){
if(!dynarr_remove(&timer_registry, registry_ptr)){
/**/SWTMR_ERR("Failed to remove timer from registry");
/**/SWTMR_DBG("registry_ptr = %p", registry_ptr);
return;
}
}
else{
//timer not in registry
}
return;
}
/* Global Function Definitions */
#if defined(SWTMR_DEBUG)
void swtmr_print_registry(void){
volatile uint32 frc2_count = RTC_REG_READ(FRC2_COUNT_ADDRESS);
uint32 time_till_fire = 0;
uint32 time = system_get_time();
timer_registry_remove_unarmed();
time = system_get_time()-time;
/**/SWTMR_DBG("registry_remove_unarmed_timers() took %u us", time);
os_timer_t** timer_array = timer_registry.data_ptr;
c_printf("\n array used(%u)/size(%u)\ttotal size(bytes)=%u\n FRC2 COUNT %u\n",
timer_registry.used, timer_registry.array_size, timer_registry.array_size * timer_registry.data_size, frc2_count);
c_printf("\n Registered timer array contents:\n");
c_printf(" %-5s %-10s %-10s %-13s %-10s %-10s %-10s\n", "idx", "ptr", "expire", "period(tick)", "period(ms)", "fire(tick)", "fire(ms)");
for(uint32 i=0; i < timer_registry.used; i++){
time_till_fire = (timer_array[i]->timer_expire - frc2_count);
c_printf(" %-5d %-10p %-10d %-13d %-10d %-10d %-10d\n", i, timer_array[i], timer_array[i]->timer_expire, timer_array[i]->timer_period, (uint32)(timer_array[i]->timer_period/312.5), time_till_fire, (uint32)(time_till_fire/312.5));
}
return;
}
void swtmr_print_suspended(void){
os_timer_t** susp_timer_array = suspended_timers.data_ptr;
c_printf("\n array used(%u)/size(%u)\ttotal size(bytes)=%u\n",
suspended_timers.used, suspended_timers.array_size, suspended_timers.array_size * suspended_timers.data_size);
c_printf("\n Suspended timer array contents:\n");
c_printf(" %-5s %-10s %-15s %-15s %-14s %-10s\n", "idx", "ptr", "time left(tick)", "time left(ms)", "period(tick)", "period(ms)");
for(uint32 i=0; i < suspended_timers.used; i++){
c_printf(" %-5d %-10p %-15d %-15d %-14d %-10d\n", i, susp_timer_array[i], susp_timer_array[i]->timer_expire, (uint32)(susp_timer_array[i]->timer_expire/312.5), susp_timer_array[i]->timer_period, (uint32)(susp_timer_array[i]->timer_period/312.5));
}
return;
}
void swtmr_print_timer_list(void){
volatile uint32 frc2_count=RTC_REG_READ(FRC2_COUNT_ADDRESS);
os_timer_t* timer_list_ptr=NULL;
uint32 time_till_fire=0;
c_printf("\n\tcurrent FRC2 count:%u\n", frc2_count);
c_printf(" timer_list contents:\n");
c_printf(" %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n", "ptr", "expire", "period", "func", "arg", "fire(tick)", "fire(ms)");
ETS_INTR_LOCK();
timer_list_ptr=timer_list;
while(timer_list_ptr != NULL){
time_till_fire=(timer_list_ptr->timer_expire - frc2_count) / 312.5;
c_printf(" %-10p %-10u %-10u %-10p %-10p %-10u %-10u\n",
timer_list_ptr, (uint32)(timer_list_ptr->timer_expire),
(uint32)(timer_list_ptr->timer_period ), timer_list_ptr->timer_func,
timer_list_ptr->timer_arg, (timer_list_ptr->timer_expire - frc2_count), time_till_fire);
timer_list_ptr=timer_list_ptr->timer_next;
}
ETS_INTR_UNLOCK();
c_printf(" NOTE: some timers in the above list belong to the SDK and can not be suspended\n");
return;
}
#endif
int swtmr_suspend(os_timer_t* timer_ptr){
int return_value = SWTMR_OK;
if(timer_ptr != NULL){
// Timer pointer was provided, suspending specified timer
return_value = timer_do_suspend(timer_ptr);
if(return_value != SWTMR_OK){
return return_value;
}
}
else{
//timer pointer not found, suspending all timers
if(timer_registry.data_ptr == NULL){
return SWTMR_REGISTRY_NO_REGISTERED_TIMERS;
}
timer_registry_remove_unarmed();
os_timer_t** tmr_reg_arr = timer_registry.data_ptr;
os_timer_t* temp_ptr = tmr_reg_arr[0];
while(temp_ptr != NULL){
return_value = timer_do_suspend(temp_ptr);
if(return_value != SWTMR_OK){
return return_value;
}
temp_ptr = tmr_reg_arr[0];
}
}
return return_value;
}
int swtmr_resume(os_timer_t* timer_ptr){
if(suspended_timers.data_ptr == NULL){
return SWTMR_SUSPEND_NO_SUSPENDED_TIMERS;
}
os_timer_t** suspended_tmr_array = suspended_timers.data_ptr;
os_timer_t** suspended_timer_ptr = NULL;
int retval=SWTMR_OK;
if(timer_ptr != NULL){
suspended_timer_ptr = timer_suspended_check(timer_ptr);
if(suspended_timer_ptr == NULL){
//timer not suspended
return SWTMR_SUSPEND_TIMER_NOT_SUSPENDED;
}
retval = timer_do_resume_single(suspended_timer_ptr);
if(retval != SWTMR_OK){
return retval;
}
}
else{
suspended_timer_ptr = &suspended_tmr_array[0];
while(suspended_timers.used > 0){
retval = timer_do_resume_single(suspended_timer_ptr);
if(retval != SWTMR_OK){
SWTMR_ERR("Unable to continue resuming timers, error(%u)", retval);
return retval;
}
suspended_timer_ptr = &suspended_tmr_array[0];
}
}
return SWTMR_OK;
}
void swtmr_register(void* timer_ptr){
if(timer_ptr == NULL){
SWTMR_DBG("error: timer_ptr is NULL");
return;
}
registry_queue_t* queue_temp = c_zalloc(sizeof(registry_queue_t));
if(queue_temp == NULL){
SWTMR_ERR("MALLOC FAIL! req:%u, free:%u", sizeof(registry_queue_t), system_get_free_heap_size());
return;
}
queue_temp->timer_ptr = timer_ptr;
if(register_queue == NULL){
register_queue = queue_temp;
if(timer_reg_task_id == false) timer_reg_task_id = task_get_id(timer_register_task);
task_post_low(timer_reg_task_id, false);
SWTMR_DBG("queue empty, adding timer(%p) to queue and posting task", timer_ptr);
}
else{
registry_queue_t* register_queue_tail = register_queue;
while(register_queue_tail->next != NULL){
register_queue_tail = register_queue_tail->next;
}
register_queue_tail->next = queue_temp;
SWTMR_DBG("queue NOT empty, appending timer(%p) to queue", timer_ptr);
}
return;
}
void swtmr_unregister(void* timer_ptr){
if(timer_ptr == NULL){
SWTMR_DBG("error: timer_ptr is NULL");
return;
}
registry_queue_t* queue_temp = c_zalloc(sizeof(registry_queue_t));
if(queue_temp == NULL){
SWTMR_ERR("MALLOC FAIL! req:%u, free:%u", sizeof(registry_queue_t), system_get_free_heap_size());
return;
}
queue_temp->timer_ptr=timer_ptr;
if(unregister_queue == NULL){
unregister_queue = queue_temp;
if(timer_unreg_task_id==false) timer_unreg_task_id=task_get_id(timer_unregister_task);
task_post_low(timer_unreg_task_id, false);
SWTMR_DBG("queue empty, adding timer(%p) to queue and posting task", timer_ptr);
}
else{
registry_queue_t* unregister_queue_tail=unregister_queue;
while(unregister_queue_tail->next != NULL){
unregister_queue_tail=unregister_queue_tail->next;
}
unregister_queue_tail->next = queue_temp;
// SWTMR_DBG("queue NOT empty, appending timer(%p) to queue", timer_ptr);
}
return;
}
const char* swtmr_errorcode2str(int error_value){
#ifdef USE_SWTMR_ERROR_STRINGS
if(SWTMR_ERROR_STRINGS[error_value] == NULL){
SWTMR_ERR("error string %d not found", error_value);
return NULL;
}
else{
return SWTMR_ERROR_STRINGS[error_value];
}
#else
SWTMR_ERR("error(%u)", error_value);
return "ERROR! for more info, use debug build";
#endif
}
bool swtmr_suspended_test(os_timer_t* timer_ptr){
os_timer_t** test_var = timer_suspended_check(timer_ptr);
if(test_var == NULL){
return false;
}
return true;
}
#endif
......@@ -76,12 +76,6 @@ static tsl2561Gain_t _tsl2561Gain = TSL2561_GAIN_1X;
static tsl2561Address_t tsl2561Address = TSL2561_ADDRESS_FLOAT;
static tsl2561Package_t tsl2561Package = TSL2561_PACKAGE_T_FN_CL;
static void delay_ms(uint16_t ms)
{
while (ms--)
os_delay_us(1000);
}
/**************************************************************************/
/*!
@brief Writes an 8 bit values over I2C
......@@ -236,13 +230,13 @@ tsl2561Error_t tsl2561GetLuminosity(uint16_t *broadband, uint16_t *ir) {
// Wait x ms for ADC to complete
switch (_tsl2561IntegrationTime) {
case TSL2561_INTEGRATIONTIME_13MS:
delay_ms(14); //systickDelay(14);
os_delay_us(14000); //systickDelay(14);
break;
case TSL2561_INTEGRATIONTIME_101MS:
delay_ms(102); //systickDelay(102);
os_delay_us(102000); //systickDelay(102);
break;
default:
delay_ms(404); //systickDelay(404);
os_delay_us(404000); //systickDelay(404);
break;
}
......
......@@ -24,7 +24,7 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
DEFINES += -DESP_INIT_DATA_DEFAULT="\"$(SDK_DIR)/bin/esp_init_data_default.bin\""
DEFINES += -DESP_INIT_DATA_DEFAULT="\"$(SDK_DIR)/bin/esp_init_data_default_v05.bin\""
#############################################################
# Recursion Magic - Don't touch this!!
......
......@@ -40,6 +40,8 @@
#include "../crypto/digests.h"
#include "../crypto/mech.h"
#include "pm/swtimer.h"
#define PROTOCOL_SECURE "wss://"
#define PROTOCOL_INSECURE "ws://"
......@@ -560,6 +562,7 @@ static void ws_initReceiveCallback(void *arg, char *buf, unsigned short len) {
os_timer_disarm(&ws->timeoutTimer);
os_timer_setfn(&ws->timeoutTimer, (os_timer_func_t *) ws_sendPingTimeout, conn);
SWTIMER_REG_CB(ws_sendPingTimeout, SWTIMER_RESUME)
os_timer_arm(&ws->timeoutTimer, WS_PING_INTERVAL_MS, true);
espconn_regist_recvcb(conn, ws_receiveCallback);
......@@ -706,6 +709,7 @@ static void dns_callback(const char *hostname, ip_addr_t *addr, void *arg) {
// Set connection timeout timer
os_timer_disarm(&ws->timeoutTimer);
os_timer_setfn(&ws->timeoutTimer, (os_timer_func_t *) ws_connectTimeout, conn);
SWTIMER_REG_CB(ws_connectTimeout, SWTIMER_RESUME)
os_timer_arm(&ws->timeoutTimer, WS_CONNECT_TIMEOUT_MS, false);
if (ws->isSecure) {
......@@ -867,6 +871,7 @@ void ws_close(ws_info *ws) {
os_timer_disarm(&ws->timeoutTimer);
os_timer_setfn(&ws->timeoutTimer, (os_timer_func_t *) ws_forceCloseTimeout, ws->conn);
SWTIMER_REG_CB(ws_forceCloseTimeout, SWTIMER_RESUME);
os_timer_arm(&ws->timeoutTimer, WS_FORCE_CLOSE_TIMEOUT_MS, false);
}
}
......@@ -6,3 +6,4 @@
!.gitignore
!blank.bin
!esp_init_data_default.bin
!esp_init_data_default_v05.bin
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