Refactor timer suspend portion of node.sleep (pmsleep) (#2287)
* pmsleep refactor
* Shortened swtmr disabled message
* Added swtimer debug module option to user_modules.h.
* Added comments to user_config.h.
* Fixed error in documentation for node.sleep()
* remove blank sntp.c that got added in during rebase onto dev(6218b92
)
* Added #ifdefs around SWTIMER_REG_CB to prevent inclusion of disabled
code
This commit is contained in:
parent
4c3d501b58
commit
96e5c026a8
|
@ -46,8 +46,6 @@ SUBDIRS= \
|
|||
fatfs \
|
||||
esp-gdbstub \
|
||||
websocket \
|
||||
swTimer \
|
||||
misc \
|
||||
pm \
|
||||
sjson \
|
||||
sqlite3 \
|
||||
|
@ -102,8 +100,6 @@ COMPONENTS_eagle.app.v6 = \
|
|||
net/libnodemcu_net.a \
|
||||
mbedtls/libmbedtls.a \
|
||||
modules/libmodules.a \
|
||||
swTimer/libswtimer.a \
|
||||
misc/libmisc.a \
|
||||
sjson/libsjson.a \
|
||||
sqlite3/libsqlite3.a \
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "node.h"
|
||||
#include "coap_timer.h"
|
||||
#include "os_type.h"
|
||||
#include "pm/swtimer.h"
|
||||
|
||||
static os_timer_t coap_timer;
|
||||
static coap_tick_t basetime = 0;
|
||||
|
@ -48,6 +49,8 @@ void coap_timer_tick(void *arg){
|
|||
void coap_timer_setup(coap_queue_t ** queue, coap_tick_t t){
|
||||
os_timer_disarm(&coap_timer);
|
||||
os_timer_setfn(&coap_timer, (os_timer_func_t *)coap_timer_tick, queue);
|
||||
SWTIMER_REG_CB(coap_timer_tick, SWTIMER_RESUME);
|
||||
//coap_timer_tick processes a queue, my guess is that it is ok to resume the timer from where it left off
|
||||
os_timer_arm(&coap_timer, t, 0); // no repeat
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "mem.h"
|
||||
#include "gpio.h"
|
||||
#include "user_interface.h"
|
||||
#include "pm/swtimer.h"
|
||||
|
||||
#include "driver/key.h"
|
||||
|
||||
|
@ -148,6 +149,8 @@ key_intr_handler(void *arg)
|
|||
// 5s, restart & enter softap mode
|
||||
os_timer_disarm(&keys->single_key[i]->key_5s);
|
||||
os_timer_setfn(&keys->single_key[i]->key_5s, (os_timer_func_t *)key_5s_cb, keys->single_key[i]);
|
||||
SWTIMER_REG_CB(key_5s_cb, SWTIMER_DROP);
|
||||
// key_5s_cb checks the state of a gpio. After resume, gpio state would be invalid
|
||||
os_timer_arm(&keys->single_key[i]->key_5s, 5000, 0);
|
||||
keys->single_key[i]->key_level = 0;
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(keys->single_key[i]->gpio_id), GPIO_PIN_INTR_POSEDGE);
|
||||
|
@ -155,6 +158,8 @@ key_intr_handler(void *arg)
|
|||
// 50ms, check if this is a real key up
|
||||
os_timer_disarm(&keys->single_key[i]->key_50ms);
|
||||
os_timer_setfn(&keys->single_key[i]->key_50ms, (os_timer_func_t *)key_50ms_cb, keys->single_key[i]);
|
||||
SWTIMER_REG_CB(key_50ms_cb, SWTIMER_DROP);
|
||||
// key_50ms_cb checks the state of a gpio. After resume, gpio state would be invalid
|
||||
os_timer_arm(&keys->single_key[i]->key_50ms, 50, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -527,6 +527,7 @@ void spi_slave_init(uint8 spi_no)
|
|||
|
||||
|
||||
#ifdef SPI_SLAVE_DEBUG
|
||||
#include "pm/swtimer.h"
|
||||
/******************************************************************************
|
||||
* FunctionName : hspi_master_readwrite_repeat
|
||||
* Description : SPI master test function for reading and writing esp8266 slave buffer,
|
||||
|
@ -545,6 +546,8 @@ void hspi_master_readwrite_repeat(void)
|
|||
temp++;
|
||||
spi_byte_write_espslave(SPI_HSPI,temp);
|
||||
os_timer_setfn(&timer2, (os_timer_func_t *)hspi_master_readwrite_repeat, NULL);
|
||||
SWTIMER_REGISTER_CB_PTR(hspi_master_readwrite_repeat, SWTIMER_RESUME);
|
||||
//hspi_master_readwrite_repeat timer will be resumed on wake up, maybe data will still be in buffer?
|
||||
os_timer_arm(&timer2, 500, 0);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -323,11 +323,14 @@ uart_autobaud_timeout(void *timer_arg)
|
|||
uart_div_modify(uart_no, divisor);
|
||||
}
|
||||
}
|
||||
#include "pm/swtimer.h"
|
||||
|
||||
static void
|
||||
uart_init_autobaud(uint32_t uart_no)
|
||||
{
|
||||
os_timer_setfn(&autobaud_timer, uart_autobaud_timeout, (void *) uart_no);
|
||||
SWTIMER_REG_CB(uart_autobaud_timeout, SWTIMER_DROP);
|
||||
//if autobaud hasn't done it's thing by the time light sleep triggered, it probably isn't going to happen.
|
||||
os_timer_arm(&autobaud_timer, 100, TRUE);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "limits.h"
|
||||
#include "httpclient.h"
|
||||
#include "stdlib.h"
|
||||
#include "pm/swtimer.h"
|
||||
|
||||
#define REDIRECTION_FOLLOW_MAX 20
|
||||
|
||||
|
@ -525,6 +526,8 @@ static void ICACHE_FLASH_ATTR http_dns_callback( const char * hostname, ip_addr_
|
|||
/* Set connection timeout timer */
|
||||
os_timer_disarm( &(req->timeout_timer) );
|
||||
os_timer_setfn( &(req->timeout_timer), (os_timer_func_t *) http_timeout_callback, conn );
|
||||
SWTIMER_REG_CB(http_timeout_callback, SWTIMER_IMMEDIATE);
|
||||
//http_timeout_callback frees memory used by this function and timer cannot be dropped
|
||||
os_timer_arm( &(req->timeout_timer), req->timeout, false );
|
||||
|
||||
#ifdef CLIENT_SSL_ENABLE
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
#ifndef __DYNARR_H__
|
||||
#define __DYNARR_H__
|
||||
#include "user_interface.h"
|
||||
#include "c_stdio.h"
|
||||
#include "c_stdlib.h"
|
||||
|
||||
//#define DYNARR_DEBUG
|
||||
//#define DYNARR_ERROR
|
||||
|
||||
|
||||
typedef struct _dynarr{
|
||||
void* data_ptr;
|
||||
size_t used;
|
||||
size_t array_size;
|
||||
size_t data_size;
|
||||
} dynarr_t;
|
||||
|
||||
bool dynarr_init(dynarr_t* array_ptr, size_t array_size, size_t data_size);
|
||||
bool dynarr_resize(dynarr_t* array_ptr, size_t elements_to_add);
|
||||
bool dynarr_remove(dynarr_t* array_ptr, void* element_ptr);
|
||||
bool dynarr_add(dynarr_t* array_ptr, void* data_ptr, size_t data_size);
|
||||
bool dynarr_boundaryCheck(dynarr_t* array_ptr, void* element_ptr);
|
||||
bool dynarr_free(dynarr_t* array_ptr);
|
||||
|
||||
|
||||
#if 0 || defined(DYNARR_DEBUG) || defined(NODE_DEBUG)
|
||||
#define DYNARR_DBG(fmt, ...) c_printf("\n DYNARR_DBG(%s): "fmt"\n", __FUNCTION__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DYNARR_DBG(...)
|
||||
|
||||
#endif
|
||||
|
||||
#if 0 || defined(DYNARR_ERROR) || defined(NODE_ERROR)
|
||||
#define DYNARR_ERR(fmt, ...) c_printf("\n DYNARR: "fmt"\n", ##__VA_ARGS__)
|
||||
#else
|
||||
#define DYNARR_ERR(...)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // __DYNARR_H__
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* swtimer.h
|
||||
*
|
||||
* Created on: Aug 4, 2017
|
||||
* Author: anonymous
|
||||
*/
|
||||
|
||||
#ifndef APP_INCLUDE_PM_SWTIMER_H_
|
||||
#define APP_INCLUDE_PM_SWTIMER_H_
|
||||
|
||||
void swtmr_cb_register(void* timer_cb_ptr, uint8 suspend_policy);
|
||||
|
||||
#define SWTIMER_RESUME 0 //save remaining time
|
||||
#define SWTIMER_RESTART 1 //use timer_period as remaining time
|
||||
#define SWTIMER_IMMEDIATE 2 //fire timer immediately after resume
|
||||
#define SWTIMER_DROP 3 //disarm timer, do not resume
|
||||
|
||||
#if defined(TIMER_SUSPEND_ENABLE)
|
||||
#define SWTIMER_REG_CB(cb_ptr, suspend_policy) do{ \
|
||||
static bool cb_ptr##_registered_flag;\
|
||||
if(!cb_ptr##_registered_flag){ \
|
||||
cb_ptr##_registered_flag = true; \
|
||||
swtmr_cb_register(cb_ptr, suspend_policy);\
|
||||
} \
|
||||
}while(0);
|
||||
#else
|
||||
#define SWTIMER_REG_CB(...)
|
||||
#endif
|
||||
|
||||
#endif /* APP_INCLUDE_PM_SWTIMER_H_ */
|
|
@ -689,11 +689,15 @@ static inline void rtc_time_switch_to_system_clock(void)
|
|||
|
||||
static inline void rtc_time_tmrfn(void* arg);
|
||||
|
||||
#include "pm/swtimer.h"
|
||||
|
||||
static void rtc_time_install_timer(void)
|
||||
{
|
||||
static ETSTimer tmr;
|
||||
|
||||
os_timer_setfn(&tmr,rtc_time_tmrfn,NULL);
|
||||
SWTIMER_REG_CB(rtc_time_tmrfn, SWTIMER_RESUME);
|
||||
//I believe the function rtc_time_tmrfn compensates for drift in the clock and updates rtc time accordingly, This timer should probably be resumed
|
||||
os_timer_arm(&tmr,10000,1);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
#ifndef __SW_TIMER_H__
|
||||
#define __SW_TIMER_H__
|
||||
#include "user_interface.h"
|
||||
//#define SWTMR_DEBUG
|
||||
#define USE_SWTMR_ERROR_STRINGS
|
||||
|
||||
#if defined(DEVELOP_VERSION)
|
||||
#define SWTMR_DEBUG
|
||||
#endif
|
||||
|
||||
#if defined(SWTMR_DEBUG)
|
||||
#define SWTMR_DBG(fmt, ...) dbg_printf("\tSWTIMER(%s):"fmt"\n", __FUNCTION__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define SWTMR_DBG(...)
|
||||
#endif
|
||||
|
||||
#if defined(NODE_ERROR)
|
||||
#define SWTMR_ERR(fmt, ...) NODE_ERR("%s"fmt"\n", "SWTIMER:", ##__VA_ARGS__)
|
||||
#else
|
||||
#define SWTMR_ERR(...)
|
||||
#endif
|
||||
|
||||
enum SWTMR_STATUS{
|
||||
SWTMR_FAIL = 0,
|
||||
SWTMR_OK = 1,
|
||||
|
||||
SWTMR_MALLOC_FAIL = 10,
|
||||
SWTMR_TIMER_NOT_ARMED,
|
||||
// SWTMR_NULL_PTR,
|
||||
|
||||
SWTMR_REGISTRY_NO_REGISTERED_TIMERS,
|
||||
|
||||
// SWTMR_SUSPEND_ARRAY_INITIALIZATION_FAILED,
|
||||
// SWTMR_SUSPEND_ARRAY_ADD_FAILED,
|
||||
// SWTMR_SUSPEND_ARRAY_REMOVE_FAILED,
|
||||
SWTMR_SUSPEND_TIMER_ALREADY_SUSPENDED,
|
||||
SWTMR_SUSPEND_TIMER_ALREADY_REARMED,
|
||||
SWTMR_SUSPEND_NO_SUSPENDED_TIMERS,
|
||||
SWTMR_SUSPEND_TIMER_NOT_SUSPENDED,
|
||||
|
||||
};
|
||||
|
||||
/* Global Function Declarations */
|
||||
void swtmr_register(void* timer_ptr);
|
||||
void swtmr_unregister(void* timer_ptr);
|
||||
int swtmr_suspend(os_timer_t* timer_ptr);
|
||||
int swtmr_resume(os_timer_t* timer_ptr);
|
||||
void swtmr_print_registry(void);
|
||||
void swtmr_print_suspended(void);
|
||||
void swtmr_print_timer_list(void);
|
||||
const char* swtmr_errorcode2str(int error_value);
|
||||
bool swtmr_suspended_test(os_timer_t* timer_ptr);
|
||||
#endif // __SW_TIMER_H__
|
|
@ -116,8 +116,8 @@ extern void luaL_assertfail(const char *file, int line, const char *message);
|
|||
#define WIFI_SDK_EVENT_MONITOR_ENABLE
|
||||
#define WIFI_EVENT_MONITOR_DISCONNECT_REASON_LIST_ENABLE
|
||||
|
||||
////#define ENABLE_TIMER_SUSPEND
|
||||
//#define PMSLEEP_ENABLE
|
||||
//#define PMSLEEP_ENABLE // Enable wifi.suspend() and node.sleep() (NOTE: node.sleep() is dependent on TIMER_SUSPEND_ENABLE)
|
||||
//#define TIMER_SUSPEND_ENABLE //Required by node.sleep()
|
||||
|
||||
|
||||
#define STRBUF_DEFAULT_INCREMENT 32
|
||||
|
|
|
@ -86,5 +86,9 @@
|
|||
//#define LUA_USE_MODULES_WS2812_EFFECTS
|
||||
//#define LUA_USE_MODULES_XPT2046
|
||||
|
||||
//debug modules
|
||||
//#define LUA_USE_MODULES_SWTMR_DBG //SWTMR timer suspend Debug functions
|
||||
|
||||
|
||||
#endif /* LUA_CROSS_COMPILER */
|
||||
#endif /* __USER_MODULES_H__ */
|
||||
|
|
|
@ -1039,6 +1039,7 @@ mdns_reg(struct mdns_info *info) {
|
|||
os_timer_disarm(&mdns_timer);
|
||||
}
|
||||
}
|
||||
#include "pm/swtimer.h"
|
||||
|
||||
/**
|
||||
* Initialize the resolver: set up the UDP pcb and configure the default server
|
||||
|
@ -1129,6 +1130,8 @@ mdns_init(struct mdns_info *info) {
|
|||
|
||||
os_timer_disarm(&mdns_timer);
|
||||
os_timer_setfn(&mdns_timer, (os_timer_func_t *)mdns_reg,ms_info);
|
||||
SWTIMER_REG_CB(mdns_reg, SWTIMER_RESTART);
|
||||
//going on the above comment, it's probably a good idea to let mdns_reg run it's course. not sure if the 1 second timing is important, so lets restart it to be safe.
|
||||
os_timer_arm(&mdns_timer, 1000, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
|
||||
#############################################################
|
||||
# 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 = libmisc.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
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
#include "misc/dynarr.h"
|
||||
|
||||
#define ARRAY_PTR_CHECK if(array_ptr == NULL || array_ptr->data_ptr == NULL){\
|
||||
/**/DYNARR_DBG("array not initialized");\
|
||||
return false; \
|
||||
}
|
||||
|
||||
bool dynarr_init(dynarr_t* array_ptr, size_t array_size, size_t data_size){
|
||||
if(array_ptr == NULL || data_size == 0 || array_size == 0){
|
||||
/**/DYNARR_DBG("Invalid parameter: array_ptr(%p) data_size(%u) array_size(%u)", array_ptr, data_size, array_size);
|
||||
return false;
|
||||
}
|
||||
if(array_ptr->data_ptr != NULL ){
|
||||
/**/DYNARR_DBG("Array already initialized: array_ptr->data_ptr=%p", array_ptr->data_ptr);
|
||||
return false;
|
||||
}
|
||||
/**/DYNARR_DBG("Array parameters:\n\t\t\tarray_size(%u)\n\t\t\tdata_size(%u)\n\t\t\ttotal size(bytes):%u", array_size, data_size, (array_size * data_size));
|
||||
|
||||
void* temp_array = c_zalloc(array_size * data_size);
|
||||
if(temp_array == NULL){
|
||||
/**/DYNARR_ERR("malloc FAIL! req:%u free:%u", (array_size * data_size), system_get_free_heap_size());
|
||||
return false;
|
||||
}
|
||||
|
||||
array_ptr->data_ptr = temp_array;
|
||||
array_ptr->array_size = array_size;
|
||||
array_ptr->data_size = data_size;
|
||||
array_ptr->used = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dynarr_resize(dynarr_t* array_ptr, size_t elements_to_add){
|
||||
ARRAY_PTR_CHECK;
|
||||
|
||||
if(elements_to_add <= 0){
|
||||
/**/DYNARR_DBG("Invalid qty: elements_to_add=%u", elements_to_add);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t new_array_size = array_ptr->array_size + elements_to_add;
|
||||
|
||||
/**/DYNARR_DBG("old size=%u\tnew size=%u\tmem used=%u",
|
||||
array_ptr->array_size, new_array_size, (new_array_size * array_ptr->data_size));
|
||||
|
||||
void* temp_array_p = c_realloc(array_ptr->data_ptr, new_array_size * array_ptr->data_size);
|
||||
if(temp_array_p == NULL){
|
||||
/**/DYNARR_ERR("malloc FAIL! req:%u free:%u", (new_array_size * array_ptr->data_size), system_get_free_heap_size());
|
||||
return false;
|
||||
}
|
||||
|
||||
array_ptr->data_ptr = temp_array_p;
|
||||
|
||||
size_t prev_size = array_ptr->array_size;
|
||||
|
||||
array_ptr->array_size = new_array_size;
|
||||
|
||||
//set memory to 0 for newly added array elements
|
||||
memset((uint8*) array_ptr->data_ptr + (prev_size * array_ptr->data_size), 0, (elements_to_add * array_ptr->data_size));
|
||||
|
||||
/**/DYNARR_DBG("Array successfully resized");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dynarr_remove(dynarr_t* array_ptr, void* element_to_remove){
|
||||
ARRAY_PTR_CHECK;
|
||||
|
||||
uint8* element_ptr = element_to_remove;
|
||||
uint8* data_ptr = array_ptr->data_ptr;
|
||||
|
||||
if(dynarr_boundaryCheck(array_ptr, element_to_remove) == FALSE){
|
||||
return false;
|
||||
}
|
||||
|
||||
//overwrite element to be removed by shifting all elements to the left
|
||||
memmove(element_ptr, element_ptr + array_ptr->data_size, (array_ptr->array_size - 1) * array_ptr->data_size - (element_ptr - data_ptr));
|
||||
|
||||
//clear newly freed element
|
||||
memset(data_ptr + ((array_ptr->array_size-1) * array_ptr->data_size), 0, array_ptr->data_size);
|
||||
|
||||
//decrement array used since we removed an element
|
||||
array_ptr->used--;
|
||||
/**/DYNARR_DBG("element(%p) removed from array", element_ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dynarr_add(dynarr_t* array_ptr, void* data_ptr, size_t data_size){
|
||||
ARRAY_PTR_CHECK;
|
||||
|
||||
if(data_size != array_ptr->data_size){
|
||||
/**/DYNARR_DBG("Invalid data size: data_size(%u) != arr->data_size(%u)", data_size, array_ptr->data_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(array_ptr->array_size == array_ptr->used){
|
||||
if(!dynarr_resize(array_ptr, (array_ptr->array_size/2))){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
memcpy(((uint8*)array_ptr->data_ptr + (array_ptr->used * array_ptr->data_size)), data_ptr, array_ptr->data_size);
|
||||
|
||||
array_ptr->used++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dynarr_boundaryCheck(dynarr_t* array_ptr, void* element_to_check){
|
||||
ARRAY_PTR_CHECK;
|
||||
|
||||
uint8* data_ptr = array_ptr->data_ptr;
|
||||
uint8* element_ptr = element_to_check;
|
||||
|
||||
if(element_ptr < data_ptr || ((element_ptr - data_ptr) / array_ptr->data_size) > array_ptr->array_size - 1){
|
||||
/**/DYNARR_DBG("element_ptr(%p) out of bounds: first element ptr:%p last element ptr:%p",
|
||||
element_ptr, data_ptr, data_ptr + ((array_ptr->array_size - 1) * array_ptr->data_size));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dynarr_free(dynarr_t* array_ptr){
|
||||
ARRAY_PTR_CHECK;
|
||||
|
||||
c_free(array_ptr->data_ptr);
|
||||
|
||||
array_ptr->data_ptr=NULL;
|
||||
array_ptr->array_size = array_ptr->used = 0;
|
||||
|
||||
/**/DYNARR_DBG("array freed");
|
||||
return true;
|
||||
}
|
||||
|
|
@ -190,7 +190,7 @@ static void cron_handle_tmr() {
|
|||
struct rtc_timeval tv;
|
||||
rtctime_gettimeofday(&tv);
|
||||
if (tv.tv_sec == 0) { // Wait for RTC time
|
||||
ets_timer_arm_new(&cron_timer, 1000, 0, 1);
|
||||
os_timer_arm(&cron_timer, 1000, 0);
|
||||
return;
|
||||
}
|
||||
time_t t = tv.tv_sec;
|
||||
|
@ -202,7 +202,7 @@ static void cron_handle_tmr() {
|
|||
diff += 60000;
|
||||
gmtime_r(&t, &tm);
|
||||
}
|
||||
ets_timer_arm_new(&cron_timer, diff, 0, 1);
|
||||
os_timer_arm(&cron_timer, diff, 0);
|
||||
cron_handle_time(tm.tm_mon + 1, tm.tm_mday, tm.tm_wday, tm.tm_hour, tm.tm_min);
|
||||
}
|
||||
|
||||
|
@ -220,11 +220,15 @@ static const LUA_REG_TYPE cron_map[] = {
|
|||
{ LSTRKEY( "reset" ), LFUNCVAL( lcron_reset ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
#include "pm/swtimer.h"
|
||||
|
||||
int luaopen_cron( lua_State *L ) {
|
||||
ets_timer_disarm(&cron_timer);
|
||||
ets_timer_setfn(&cron_timer, cron_handle_tmr, 0);
|
||||
ets_timer_arm_new(&cron_timer, 1000, 0, 1);
|
||||
os_timer_disarm(&cron_timer);
|
||||
os_timer_setfn(&cron_timer, cron_handle_tmr, 0);
|
||||
SWTIMER_REG_CB(cron_handle_tmr, SWTIMER_RESTART);
|
||||
//cron_handle_tmr determines when to execute a scheduled cron job
|
||||
//My guess: To be sure to give the other modules required by cron enough time to get to a ready state, restart cron_timer.
|
||||
os_timer_arm(&cron_timer, 1000, 0);
|
||||
luaL_rometatable(L, "cron.entry", (void *)cronent_map);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -134,6 +134,8 @@ static int ds18b20_lua_setting(lua_State *L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#include "pm/swtimer.h"
|
||||
|
||||
// Reads sensor values from all devices
|
||||
// Lua: ds18b20.read(function(INDEX, ROM, RES, TEMP, TEMP_DEC, PAR) print(INDEX, ROM, RES, TEMP, TEMP_DEC, PAR) end, ROM[, FAMILY])
|
||||
static int ds18b20_lua_read(lua_State *L) {
|
||||
|
@ -173,6 +175,9 @@ static int ds18b20_lua_read(lua_State *L) {
|
|||
onewire_write(ds18b20_bus_pin, DS18B20_ROM_SKIP, 0);
|
||||
onewire_write(ds18b20_bus_pin, DS18B20_FUNC_CONVERT, 1);
|
||||
os_timer_setfn(&ds18b20_timer, (os_timer_func_t *)ds18b20_lua_readoutdone, NULL);
|
||||
SWTIMER_REG_CB(ds18b20_lua_readoutdone, SWTIMER_DROP);
|
||||
//The function ds18b20_lua_readoutdone reads the temperature from the sensor(s) after a set amount of time depending on temperature resolution
|
||||
//MY guess: If this timer manages to get suspended before it fires and the temperature data is time sensitive then resulting data would be invalid and should be discarded
|
||||
|
||||
switch (ds18b20_device_res) {
|
||||
case (9):
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -76,7 +76,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)
|
||||
|
@ -89,6 +89,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;
|
||||
|
||||
|
@ -101,6 +102,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
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
@ -155,6 +157,11 @@ static int lrotary_setup( lua_State* L )
|
|||
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;
|
||||
|
@ -708,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) {
|
||||
|
|
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -429,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
|
||||
|
@ -511,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()
|
||||
|
@ -963,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))
|
||||
|
@ -976,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))
|
||||
|
@ -994,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);
|
||||
|
@ -1910,10 +1923,8 @@ static const LUA_REG_TYPE wifi_map[] = {
|
|||
{ 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 ) },
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#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(¤t_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");
|
||||
|
|
|
@ -0,0 +1,545 @@
|
|||
/* 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, ®ister_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
|
||||
}
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
|
||||
#############################################################
|
||||
# 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
|
||||
|
|
@ -1,632 +0,0 @@
|
|||
/* 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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -333,30 +333,32 @@ Put NodeMCU in light sleep mode to reduce current consumption.
|
|||
|
||||
* NodeMCU can not enter light sleep mode if wifi is suspended.
|
||||
* All active timers will be suspended and then resumed when NodeMCU wakes from sleep.
|
||||
* Any previously suspended timers will be resumed when NodeMCU wakes from sleep.
|
||||
|
||||
!!! attention
|
||||
This is disabled by default. Modify `PMSLEEP_ENABLE` in `app/include/user_config.h` to enable it.
|
||||
|
||||
#### Syntax
|
||||
`node.sleep({wake_gpio[, duration, int_type, resume_cb, preserve_mode]})`
|
||||
<!---`node.sleep({wake_pin[, duration, int_type, resume_cb, preserve_mode]})`--->
|
||||
`node.sleep({wake_pin[, int_type, resume_cb, preserve_mode]})`
|
||||
|
||||
#### Parameters
|
||||
- `duration` Sleep duration in microseconds(μs). If a sleep duration of `0` is specified, suspension will be indefinite (Range: 0 or 50000 - 268435454 μs (0:4:28.000454))
|
||||
- `wake_pin` 1-12, pin to attach wake interrupt to. Note that pin 0(GPIO 16) does not support interrupts.
|
||||
- If sleep duration is indefinite, `wake_pin` must be specified
|
||||
- Please refer to the [`GPIO module`](gpio.md) for more info on the pin map.
|
||||
- `int_type` type of interrupt that you would like to wake on. (Optional, Default: `node.INT_LOW`)
|
||||
- valid interrupt modes:
|
||||
- `node.INT_UP` Rising edge
|
||||
- `node.INT_DOWN` Falling edge
|
||||
- `node.INT_BOTH` Both edges
|
||||
- `node.INT_LOW` Low level
|
||||
- `node.INT_HIGH` High level
|
||||
- `resume_cb` Callback to execute when WiFi wakes from suspension. (Optional)
|
||||
- `preserve_mode` preserve current WiFi mode through node sleep. (Optional, Default: true)
|
||||
- If true, Station and StationAP modes will automatically reconnect to previously configured Access Point when NodeMCU resumes.
|
||||
- If false, discard WiFi mode and leave NodeMCU in `wifi.NULL_MODE`. WiFi mode will be restored to original mode on restart.
|
||||
<!--- timed light_sleep currently does not work, the 'duration' parameter is here as a place holder--->
|
||||
<!--- * `duration` Sleep duration in microseconds(μs). If a sleep duration of `0` is specified, suspension will be indefinite (Range: 0 or 50000 - 268435454 μs (0:4:28.000454))--->
|
||||
|
||||
* `wake_pin` 1-12, pin to attach wake interrupt to. Note that pin 0(GPIO 16) does not support interrupts.
|
||||
<!---* If sleep duration is indefinite, `wake_pin` must be specified--->
|
||||
* Please refer to the [`GPIO module`](gpio.md) for more info on the pin map.
|
||||
* `int_type` type of interrupt that you would like to wake on. (Optional, Default: `node.INT_LOW`)
|
||||
* valid interrupt modes:
|
||||
* `node.INT_UP` Rising edge
|
||||
* `node.INT_DOWN` Falling edge
|
||||
* `node.INT_BOTH` Both edges
|
||||
* `node.INT_LOW` Low level
|
||||
* `node.INT_HIGH` High level
|
||||
* `resume_cb` Callback to execute when WiFi wakes from suspension. (Optional)
|
||||
* `preserve_mode` preserve current WiFi mode through node sleep. (Optional, Default: true)
|
||||
* If true, Station and StationAP modes will automatically reconnect to previously configured Access Point when NodeMCU resumes.
|
||||
* If false, discard WiFi mode and leave NodeMCU in `wifi.NULL_MODE`. WiFi mode will be restored to original mode on restart.
|
||||
|
||||
#### Returns
|
||||
- `nil`
|
||||
|
@ -379,15 +381,15 @@ Put NodeMCU in light sleep mode to reduce current consumption.
|
|||
cfg.preserve_mode=false
|
||||
|
||||
node.sleep(cfg)
|
||||
|
||||
```
|
||||
<!---
|
||||
--Put NodeMCU in light sleep mode for 10 seconds with resume callback
|
||||
cfg={}
|
||||
cfg.duration=10*1000*1000
|
||||
cfg.resume_cb=function() print("WiFi resume") end
|
||||
|
||||
node.sleep(cfg)
|
||||
|
||||
```
|
||||
--->
|
||||
|
||||
#### See also
|
||||
- [`wifi.suspend()`](wifi.md#wifisuspend)
|
||||
|
|
|
@ -62,11 +62,9 @@ Functions supported in timer object:
|
|||
- [`t:alarm()`](#tmralarm)
|
||||
- [`t:interval()`](#tmrinterval)
|
||||
- [`t:register()`](#tmrregister)
|
||||
- [`t:resume()`](#tmrresume)
|
||||
- [`t:start()`](#tmrstart)
|
||||
- [`t:state()`](#tmrstate)
|
||||
- [`t:stop()`](#tmrstop)
|
||||
- [`t:suspend()`](#tmrsuspend)
|
||||
- [`t:unregister()`](#tmrunregister)
|
||||
|
||||
#### Parameters
|
||||
|
@ -184,61 +182,6 @@ mytimer:start()
|
|||
- [`tmr.create()`](#tmrcreate)
|
||||
- [`tmr.alarm()`](#tmralarm)
|
||||
|
||||
## tmr.resume()
|
||||
|
||||
Resume an individual timer.
|
||||
|
||||
Resumes a timer that has previously been suspended with either `tmr.suspend` or `tmr.suspend_all`
|
||||
|
||||
#### Syntax
|
||||
`tmr.resume(id/ref)`
|
||||
|
||||
#### Parameters
|
||||
`id/ref` timer id (0-6) or object, obsolete for OO API (→ [`tmr.create()`](#tmrcreate))
|
||||
|
||||
#### Returns
|
||||
`true` if timer was resumed successfully
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
--resume timer mytimer
|
||||
mytimer:resume()
|
||||
|
||||
--alternate metod
|
||||
tmr.resume(mytimer)
|
||||
|
||||
```
|
||||
#### See also
|
||||
- [`tmr.suspend()`](#tmrsuspend)
|
||||
- [`tmr.suspend_all()`](#tmrsuspendall)
|
||||
- [`tmr.resume_all()`](#tmrresumeall)
|
||||
|
||||
## tmr.resume_all()
|
||||
|
||||
Resume all timers.
|
||||
|
||||
Resumes all timers including those previously been suspended with either `tmr.suspend` or `tmr.suspend_all`
|
||||
|
||||
#### Syntax
|
||||
`tmr.resume_all()`
|
||||
|
||||
#### Parameters
|
||||
none
|
||||
|
||||
#### Returns
|
||||
`true` if timers were resumed successfully
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
--resume all previously suspended timers
|
||||
tmr.resume_all()
|
||||
|
||||
```
|
||||
#### See also
|
||||
- [`tmr.suspend()`](#tmrsuspend)
|
||||
- [`tmr.suspend_all()`](#tmrsuspendall)
|
||||
- [`tmr.resume()`](#tmrresume)
|
||||
|
||||
## tmr.softwd()
|
||||
|
||||
Provides a simple software watchdog, which needs to be re-armed or disabled before it expires, or the system will be restarted.
|
||||
|
@ -336,72 +279,6 @@ if not mytimer:stop() then print("timer not stopped, not registered?") end
|
|||
- [`tmr.stop()`](#tmrstop)
|
||||
- [`tmr.unregister()`](#tmrunregister)
|
||||
|
||||
## tmr.suspend()
|
||||
|
||||
Suspend an armed timer.
|
||||
|
||||
!!! attention
|
||||
This is disabled by default. Modify `ENABLE_TIMER_SUSPEND` in `app/include/user_config.h` to enable it.
|
||||
|
||||
* Timers can be suspended at any time after they are armed.
|
||||
* If a timer is rearmed with `tmr.start` or `tmr.alarm` any matching suspended timers will be discarded.
|
||||
|
||||
#### Syntax
|
||||
`tmr.suspend(id/ref)`
|
||||
|
||||
#### Parameters
|
||||
`id/ref` timer id (0-6) or object, obsolete for OO API (→ [`tmr.create()`](#tmrcreate))
|
||||
|
||||
#### Returns
|
||||
`true` if timer was resumed successfully
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
--suspend timer mytimer
|
||||
mytimer:suspend()
|
||||
|
||||
--alternate metod
|
||||
tmr.suspend(mytimer)
|
||||
|
||||
```
|
||||
#### See also
|
||||
- [`tmr.suspend_all()`](#tmrsuspendall)
|
||||
- [`tmr.resume()`](#tmrresume)
|
||||
- [`tmr.resume_all()`](#tmrresumeall)
|
||||
|
||||
|
||||
## tmr.suspend_all()
|
||||
|
||||
Suspend all currently armed timers.
|
||||
|
||||
!!! attention
|
||||
This is disabled by default. Modify `ENABLE_TIMER_SUSPEND` in `app/include/user_config.h` to enable it.
|
||||
|
||||
!!! Warning
|
||||
This function suspends ALL active timers, including any active timers started by the NodeMCU subsystem or other modules. this may cause parts of your program to stop functioning properly.
|
||||
USE THIS FUNCTION AT YOUR OWN RISK!
|
||||
|
||||
#### Syntax
|
||||
`tmr.suspend_all()`
|
||||
|
||||
#### Parameters
|
||||
none
|
||||
|
||||
#### Returns
|
||||
`true` if timers were suspended successfully
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
--suspend timer mytimer
|
||||
tmr.suspend_all()
|
||||
|
||||
```
|
||||
#### See also
|
||||
- [`tmr.suspendl()`](#tmrsuspend)
|
||||
- [`tmr.resume()`](#tmrresume)
|
||||
- [`tmr.resume_all()`](#tmrresumeall)
|
||||
|
||||
|
||||
## tmr.time()
|
||||
|
||||
Returns the system uptime, in seconds. Limited to 31 bits, after that it wraps around back to zero.
|
||||
|
|
|
@ -15,15 +15,4 @@ void call_user_start(void);
|
|||
|
||||
#include_next "osapi.h"
|
||||
|
||||
#ifdef ENABLE_TIMER_SUSPEND
|
||||
extern void swtmr_register(void* timer_ptr);
|
||||
#undef os_timer_arm
|
||||
#define os_timer_arm(timer_ptr, duration, mode) do{swtmr_register(timer_ptr); \
|
||||
ets_timer_arm_new(timer_ptr, duration, mode, 1);}while(0);
|
||||
|
||||
extern void swtmr_unregister(void* timer_ptr);
|
||||
#undef os_timer_disarm
|
||||
#define os_timer_disarm(timer_ptr) do{swtmr_unregister(timer_ptr); ets_timer_disarm(timer_ptr);}while(0);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue