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

@ -10,10 +10,10 @@
static volatile int cs = -1;
static ETSTimer resetTim;
volatile u32 ansi_parser_char_cnt = 0;
static void ICACHE_FLASH_ATTR
resetParserCb(void *arg) {
void ICACHE_FLASH_ATTR
ansi_parser_reset(void) {
if (cs != ansi_start) {
cs = ansi_start;
apars_reset_utf8buffer();
@ -74,6 +74,8 @@ ansi_parser(const char *newdata, size_t len)
static char osc_buffer[OSC_CHAR_MAX];
static int osc_bi;
ansi_parser_char_cnt++;
if (len == 0) len = strlen(newdata);
// Load new data to Ragel vars
@ -90,13 +92,6 @@ ansi_parser(const char *newdata, size_t len)
#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
for(int i=len; i<HISTORY_LEN; i++) {
history[i-len] = history[i];

@ -13,6 +13,8 @@
#include "ansi_parser_callbacks.h"
#include "wifimgr.h"
#include "persist.h"
#include "screen.h"
#include "ansi_parser.h"
#define BTNGPIO 0
@ -21,6 +23,28 @@ static bool enable_ap_button = false;
static ETSTimer resetBtntimer;
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.
// 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_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.
if (GPIO_INPUT_GET(BTNGPIO) == 0) {
// starting "in BOOT mode" - do not install the AP reset timer

Loading…
Cancel
Save