workaround for buggy ets_timer_disarm causing bootloop in some devices with perser tiemout > 0

pull/111/merge
Ondřej Hruška 7 years ago
parent 35393827a9
commit 2ca8bf1483
  1. 65
      user/ansi_parser.c
  2. 4
      user/ansi_parser.h
  3. 15
      user/ansi_parser.rl
  4. 28
      user/io.c

@ -40,10 +40,10 @@ static const int ansi_en_main = 1;
static volatile int cs = -1; static volatile int cs = -1;
static ETSTimer resetTim; volatile u32 ansi_parser_char_cnt = 0;
static void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
resetParserCb(void *arg) { ansi_parser_reset(void) {
if (cs != ansi_start) { if (cs != ansi_start) {
cs = ansi_start; cs = ansi_start;
apars_reset_utf8buffer(); apars_reset_utf8buffer();
@ -104,6 +104,8 @@ ansi_parser(const char *newdata, size_t len)
static char osc_buffer[OSC_CHAR_MAX]; static char osc_buffer[OSC_CHAR_MAX];
static int osc_bi; static int osc_bi;
ansi_parser_char_cnt++;
if (len == 0) len = strlen(newdata); if (len == 0) len = strlen(newdata);
// Load new data to Ragel vars // Load new data to Ragel vars
@ -114,25 +116,18 @@ ansi_parser(const char *newdata, size_t len)
// Init Ragel on the first run // Init Ragel on the first run
if (cs == -1) { if (cs == -1) {
/* #line 118 "user/ansi_parser.c" */ /* #line 120 "user/ansi_parser.c" */
{ {
cs = ansi_start; cs = ansi_start;
} }
/* #line 87 "user/ansi_parser.rl" */ /* #line 89 "user/ansi_parser.rl" */
#if DEBUG_ANSI #if DEBUG_ANSI
memset(history, 0, sizeof(history)); memset(history, 0, sizeof(history));
#endif #endif
} }
// schedule state reset after idle timeout
if (termconf->parser_tout_ms > 0) {
os_timer_disarm(&resetTim);
os_timer_setfn(&resetTim, resetParserCb, NULL);
os_timer_arm(&resetTim, termconf->parser_tout_ms, 0);
}
#if DEBUG_ANSI #if DEBUG_ANSI
for(int i=len; i<HISTORY_LEN; i++) { for(int i=len; i<HISTORY_LEN; i++) {
history[i-len] = history[i]; history[i-len] = history[i];
@ -142,7 +137,7 @@ ansi_parser(const char *newdata, size_t len)
// The parser // The parser
/* #line 146 "user/ansi_parser.c" */ /* #line 141 "user/ansi_parser.c" */
{ {
const char *_acts; const char *_acts;
unsigned int _nacts; unsigned int _nacts;
@ -449,7 +444,7 @@ execFuncs:
while ( _nacts-- > 0 ) { while ( _nacts-- > 0 ) {
switch ( *_acts++ ) { switch ( *_acts++ ) {
case 0: case 0:
/* #line 117 "user/ansi_parser.rl" */ /* #line 112 "user/ansi_parser.rl" */
{ {
if ((*p) != 0) { if ((*p) != 0) {
apars_handle_plainchar((*p)); apars_handle_plainchar((*p));
@ -457,7 +452,7 @@ execFuncs:
} }
break; break;
case 1: case 1:
/* #line 126 "user/ansi_parser.rl" */ /* #line 121 "user/ansi_parser.rl" */
{ {
// Reset the CSI builder // Reset the CSI builder
csi_leading = csi_char = 0; csi_leading = csi_char = 0;
@ -473,13 +468,13 @@ execFuncs:
} }
break; break;
case 2: case 2:
/* #line 140 "user/ansi_parser.rl" */ /* #line 135 "user/ansi_parser.rl" */
{ {
csi_leading = (*p); csi_leading = (*p);
} }
break; break;
case 3: case 3:
/* #line 144 "user/ansi_parser.rl" */ /* #line 139 "user/ansi_parser.rl" */
{ {
if (csi_cnt == 0) csi_cnt = 1; if (csi_cnt == 0) csi_cnt = 1;
// x10 + digit // x10 + digit
@ -489,7 +484,7 @@ execFuncs:
} }
break; break;
case 4: case 4:
/* #line 152 "user/ansi_parser.rl" */ /* #line 147 "user/ansi_parser.rl" */
{ {
if (csi_cnt == 0) csi_cnt = 1; // handle case when first arg is empty if (csi_cnt == 0) csi_cnt = 1; // handle case when first arg is empty
csi_cnt++; csi_cnt++;
@ -497,7 +492,7 @@ execFuncs:
} }
break; break;
case 5: case 5:
/* #line 158 "user/ansi_parser.rl" */ /* #line 153 "user/ansi_parser.rl" */
{ {
csi_char = (*p); csi_char = (*p);
apars_handle_CSI(csi_leading, csi_n, csi_cnt, csi_char); apars_handle_CSI(csi_leading, csi_n, csi_cnt, csi_char);
@ -505,7 +500,7 @@ execFuncs:
} }
break; break;
case 6: case 6:
/* #line 164 "user/ansi_parser.rl" */ /* #line 159 "user/ansi_parser.rl" */
{ {
ansi_warn("Invalid escape sequence discarded."); ansi_warn("Invalid escape sequence discarded.");
apars_handle_badseq(); apars_handle_badseq();
@ -513,7 +508,7 @@ execFuncs:
} }
break; break;
case 7: case 7:
/* #line 182 "user/ansi_parser.rl" */ /* #line 177 "user/ansi_parser.rl" */
{ {
csi_ni = 0; csi_ni = 0;
@ -529,7 +524,7 @@ execFuncs:
} }
break; break;
case 8: case 8:
/* #line 197 "user/ansi_parser.rl" */ /* #line 192 "user/ansi_parser.rl" */
{ {
osc_bi = 0; osc_bi = 0;
osc_buffer[0] = '\0'; osc_buffer[0] = '\0';
@ -537,20 +532,20 @@ execFuncs:
} }
break; break;
case 9: case 9:
/* #line 203 "user/ansi_parser.rl" */ /* #line 198 "user/ansi_parser.rl" */
{ {
apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]); apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 10: case 10:
/* #line 208 "user/ansi_parser.rl" */ /* #line 203 "user/ansi_parser.rl" */
{ {
osc_buffer[osc_bi++] = (*p); osc_buffer[osc_bi++] = (*p);
} }
break; break;
case 11: case 11:
/* #line 212 "user/ansi_parser.rl" */ /* #line 207 "user/ansi_parser.rl" */
{ {
osc_buffer[osc_bi++] = '\0'; osc_buffer[osc_bi++] = '\0';
apars_handle_OSC_SetTitle(osc_buffer); apars_handle_OSC_SetTitle(osc_buffer);
@ -558,7 +553,7 @@ execFuncs:
} }
break; break;
case 12: case 12:
/* #line 218 "user/ansi_parser.rl" */ /* #line 213 "user/ansi_parser.rl" */
{ {
osc_buffer[osc_bi++] = '\0'; osc_buffer[osc_bi++] = '\0';
apars_handle_OSC_SetButton(csi_n[0], osc_buffer); apars_handle_OSC_SetButton(csi_n[0], osc_buffer);
@ -566,28 +561,28 @@ execFuncs:
} }
break; break;
case 13: case 13:
/* #line 250 "user/ansi_parser.rl" */ /* #line 245 "user/ansi_parser.rl" */
{ {
apars_handle_hashCode((*p)); apars_handle_hashCode((*p));
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 14: case 14:
/* #line 255 "user/ansi_parser.rl" */ /* #line 250 "user/ansi_parser.rl" */
{ {
apars_handle_shortCode((*p)); apars_handle_shortCode((*p));
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 15: case 15:
/* #line 260 "user/ansi_parser.rl" */ /* #line 255 "user/ansi_parser.rl" */
{ {
apars_handle_setXCtrls((*p)); apars_handle_setXCtrls((*p));
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 16: case 16:
/* #line 265 "user/ansi_parser.rl" */ /* #line 260 "user/ansi_parser.rl" */
{ {
// abuse the buffer for storing the leading char // abuse the buffer for storing the leading char
osc_buffer[0] = (*p); osc_buffer[0] = (*p);
@ -595,13 +590,13 @@ execFuncs:
} }
break; break;
case 17: case 17:
/* #line 271 "user/ansi_parser.rl" */ /* #line 266 "user/ansi_parser.rl" */
{ {
apars_handle_characterSet(osc_buffer[0], (*p)); apars_handle_characterSet(osc_buffer[0], (*p));
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
/* #line 605 "user/ansi_parser.c" */ /* #line 600 "user/ansi_parser.c" */
} }
} }
goto _again; goto _again;
@ -619,7 +614,7 @@ _again:
while ( __nacts-- > 0 ) { while ( __nacts-- > 0 ) {
switch ( *__acts++ ) { switch ( *__acts++ ) {
case 6: case 6:
/* #line 164 "user/ansi_parser.rl" */ /* #line 159 "user/ansi_parser.rl" */
{ {
ansi_warn("Invalid escape sequence discarded."); ansi_warn("Invalid escape sequence discarded.");
apars_handle_badseq(); apars_handle_badseq();
@ -628,7 +623,7 @@ _again:
goto _again;} goto _again;}
} }
break; break;
/* #line 632 "user/ansi_parser.c" */ /* #line 627 "user/ansi_parser.c" */
} }
} }
} }
@ -636,7 +631,7 @@ goto _again;}
_out: {} _out: {}
} }
/* #line 295 "user/ansi_parser.rl" */ /* #line 290 "user/ansi_parser.rl" */
} }

@ -19,6 +19,10 @@ extern void apars_handle_characterSet(char leadchar, char c);
extern void apars_handle_setXCtrls(char c); extern void apars_handle_setXCtrls(char c);
extern void apars_reset_utf8buffer(void); extern void apars_reset_utf8buffer(void);
void ansi_parser_reset(void);
extern volatile u32 ansi_parser_char_cnt;
// defined in the makefile // defined in the makefile
#if DEBUG_ANSI #if DEBUG_ANSI
#define ansi_warn warn #define ansi_warn warn

@ -10,10 +10,10 @@
static volatile int cs = -1; static volatile int cs = -1;
static ETSTimer resetTim; volatile u32 ansi_parser_char_cnt = 0;
static void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
resetParserCb(void *arg) { ansi_parser_reset(void) {
if (cs != ansi_start) { if (cs != ansi_start) {
cs = ansi_start; cs = ansi_start;
apars_reset_utf8buffer(); apars_reset_utf8buffer();
@ -74,6 +74,8 @@ ansi_parser(const char *newdata, size_t len)
static char osc_buffer[OSC_CHAR_MAX]; static char osc_buffer[OSC_CHAR_MAX];
static int osc_bi; static int osc_bi;
ansi_parser_char_cnt++;
if (len == 0) len = strlen(newdata); if (len == 0) len = strlen(newdata);
// Load new data to Ragel vars // Load new data to Ragel vars
@ -90,13 +92,6 @@ ansi_parser(const char *newdata, size_t len)
#endif #endif
} }
// schedule state reset after idle timeout
if (termconf->parser_tout_ms > 0) {
os_timer_disarm(&resetTim);
os_timer_setfn(&resetTim, resetParserCb, NULL);
os_timer_arm(&resetTim, termconf->parser_tout_ms, 0);
}
#if DEBUG_ANSI #if DEBUG_ANSI
for(int i=len; i<HISTORY_LEN; i++) { for(int i=len; i<HISTORY_LEN; i++) {
history[i-len] = history[i]; history[i-len] = history[i];

@ -13,6 +13,8 @@
#include "ansi_parser_callbacks.h" #include "ansi_parser_callbacks.h"
#include "wifimgr.h" #include "wifimgr.h"
#include "persist.h" #include "persist.h"
#include "screen.h"
#include "ansi_parser.h"
#define BTNGPIO 0 #define BTNGPIO 0
@ -21,6 +23,28 @@ static bool enable_ap_button = false;
static ETSTimer resetBtntimer; static ETSTimer resetBtntimer;
static ETSTimer blinkyTimer; static ETSTimer blinkyTimer;
static ETSTimer ansiParserResetTimer;
static void ICACHE_FLASH_ATTR ansiParserResetTimerCb(void *arg) {
static u32 last_charcnt = 0;
static int same_charcnt = -1;
if (termconf->parser_tout_ms == 0) return;
if (last_charcnt != ansi_parser_char_cnt) {
last_charcnt = ansi_parser_char_cnt;
same_charcnt = 0;
}
else {
if (same_charcnt != -1) {
same_charcnt++;
if (same_charcnt > termconf->parser_tout_ms) {
ansi_parser_reset();
same_charcnt = -1;
}
}
}
}
// Holding BOOT pin triggers AP reset, then Factory Reset. // Holding BOOT pin triggers AP reset, then Factory Reset.
// Indicate that by blinking the on-board LED. // Indicate that by blinking the on-board LED.
@ -102,6 +126,10 @@ void ICACHE_FLASH_ATTR ioInit() {
os_timer_setfn(&resetBtntimer, resetBtnTimerCb, NULL); os_timer_setfn(&resetBtntimer, resetBtnTimerCb, NULL);
os_timer_arm(&resetBtntimer, 500, 1); os_timer_arm(&resetBtntimer, 500, 1);
os_timer_disarm(&ansiParserResetTimer);
os_timer_setfn(&ansiParserResetTimer, ansiParserResetTimerCb, NULL);
os_timer_arm(&ansiParserResetTimer, 1, 1);
// One way to enter AP mode - hold GPIO0 low. // One way to enter AP mode - hold GPIO0 low.
if (GPIO_INPUT_GET(BTNGPIO) == 0) { if (GPIO_INPUT_GET(BTNGPIO) == 0) {
// starting "in BOOT mode" - do not install the AP reset timer // starting "in BOOT mode" - do not install the AP reset timer

Loading…
Cancel
Save