From c570a31751ab472112f4e4332012040c5f031f9e Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Wed, 1 Jul 2015 23:22:50 -0700 Subject: [PATCH] add UART debug log control UI --- html/console.js | 37 +++++++++++++++++++ html/log.html | 29 ++++++++++----- html/style.css | 5 +++ html/ui.js | 25 ------------- serial/console.c | 1 - user/config.c | 92 +++++++++++++++++++++++++++++++++--------------- user/config.h | 3 +- user/log.c | 38 ++++++++++++++++++-- user/log.h | 9 +++-- user/user_main.c | 1 + 10 files changed, 173 insertions(+), 67 deletions(-) diff --git a/html/console.js b/html/console.js index 355c797..8694a61 100644 --- a/html/console.js +++ b/html/console.js @@ -33,3 +33,40 @@ function updateText(resp) { function retryLoad(repeat) { fetchText(1000, repeat); } + +//===== Console page + +function showRate(rate) { + rates.forEach(function(r) { + var el = $("#"+r+"-button"); + el.className = el.className.replace(" button-selected", ""); + }); + + var el = $("#"+rate+"-button"); + if (el != null) el.className += " button-selected"; +} + +function baudButton(baud) { + $("#baud-btns").appendChild(m( + ' '+baud+'')); + + $("#"+baud+"-button").addEventListener("click", function(e) { + e.preventDefault(); + ajaxSpin('POST', "/console/baud?rate="+baud, + function(resp) { showNotification("" + baud + " baud set"); showRate(baud); }, + function(s, st) { showWarning("Error setting baud rate: " + st); } + ); + }); +} + +//===== Log page + +function showDbgMode(mode) { + var btns = $('.dbg-btn'); + for (var i=0; i < btns.length; i++) { + if (btns[i].id === "dbg-"+mode) + addClass(btns[i], "button-selected"); + else + removeClass(btns[i], "button-selected"); + } +} diff --git a/html/log.html b/html/log.html index 717e48c..46ec785 100644 --- a/html/log.html +++ b/html/log.html @@ -4,15 +4,17 @@
+

The debug log shows the most recent characters printed by the esp-link software itself to + its own debug log.

-
-

- Refresh -

-
-

- The debug log shows the most recent characters printed by the esp-link software itself to - its own debug log. +

+ Refresh +

+

+ UART debug log: + auto + off + on


@@ -30,6 +32,17 @@
       e.preventDefault();
       fetchText(100, false);
     });
+
+    ["auto", "off", "on"].forEach(function(mode) {
+      bnd($('#dbg-'+mode), "click", function(el) {
+        ajaxJsonSpin('POST', "/log/dbg?mode="+mode,
+          function(data) { showNotification("UART mode " + data.mode); showDbgMode(data.mode); },
+          function(s, st) { showWarning("Error setting UART mode: " + st); }
+        );
+      });
+    });
+
+    ajaxJson('GET', "/log/dbg", function(data) { showDbgMode(data.mode); }, function() {});
   });
 
 
diff --git a/html/style.css b/html/style.css
index 122630e..4fa393a 100644
--- a/html/style.css
+++ b/html/style.css
@@ -146,6 +146,11 @@ pre.console a {
 	color: #66ff66;
 }
 
+/* log page */
+.dbg-btn, #refresh-button {
+	vertical-align: baseline;
+}
+
 .lock-icon {
 	background-image: url("/wifi/icons.png");
 	background-color: transparent;
diff --git a/html/ui.js b/html/ui.js
index 4b64c60..b67f077 100644
--- a/html/ui.js
+++ b/html/ui.js
@@ -263,31 +263,6 @@ onLoad(function() {
   getMenu();
 });
 
-//===== Console page
-
-function showRate(rate) {
-    rates.forEach(function(r) {
-      var el = $("#"+r+"-button");
-      el.className = el.className.replace(" button-selected", "");
-    });
-
-    var el = $("#"+rate+"-button");
-    if (el != null) el.className += " button-selected";
-  }
-
-function baudButton(baud) {
-  $("#baud-btns").appendChild(m(
-    ' '+baud+''));
-
-  $("#"+baud+"-button").addEventListener("click", function(e) {
-    e.preventDefault();
-    ajaxSpin('POST', "/console/baud?rate="+baud,
-      function(resp) { showNotification("" + baud + " baud set"); showRate(baud); },
-      function(s, st) { showWarning("Error setting baud rate: ", st); }
-    );
-  });
-}
-
 //===== Wifi info
 
 function showWifiInfo(data) {
diff --git a/serial/console.c b/serial/console.c
index 4ab3f0e..a4cf1a8 100644
--- a/serial/console.c
+++ b/serial/console.c
@@ -62,7 +62,6 @@ ajaxConsoleBaud(HttpdConnData *connData) {
 	if (len > 0) {
 		int rate = atoi(buff);
 		if (rate >= 9600 && rate <= 1000000) {
-			jsonHeader(connData, 200);
 			uart0_baud(rate);
 			flashConfig.baud_rate = rate;
 			status = configSave() ? 200 : 400;
diff --git a/user/config.c b/user/config.c
index 90b9905..b840c8f 100644
--- a/user/config.c
+++ b/user/config.c
@@ -6,37 +6,64 @@
 #include "config.h"
 #include "espfs.h"
 
+// hack: this from LwIP
+extern uint16_t inet_chksum(void *dataptr, uint16_t len);
+
 FlashConfig flashConfig;
 FlashConfig flashDefault = {
-  33, 0,
+  33, 0, 0,
   MCU_RESET_PIN, MCU_ISP_PIN, LED_CONN_PIN, LED_SERIAL_PIN,
   115200,
   "esp-link\0                       ", // hostname
   0, 0x00ffffff, 0,                    // static ip, netmask, gateway
+  0,                                   // log mode
 };
 
-#define FLASH_MAGIC  (0xaa55aa55)
+typedef union {
+  FlashConfig fc;
+  uint8_t     block[128];
+} FlashFull;
+
+#define FLASH_MAGIC  (0xaa55)
 
 #define FLASH_ADDR   (0x3E000)
 #define FLASH_SECT   (4096)
 static int flash_pri; // primary flash sector (0 or 1, or -1 for error)
 
+#if 0
+static void memDump(void *addr, int len) {
+  for (int i=0; i>12) != SPI_FLASH_RESULT_OK)
     return false; // no harm done, give up
+  // calculate CRC
+  ff.fc.seq = seq;
+  ff.fc.magic = FLASH_MAGIC;
+  ff.fc.crc = 0;
+  //os_printf("cksum of: ");
+  //memDump(&ff, sizeof(ff));
+  ff.fc.crc = inet_chksum(&ff, sizeof(ff));
+  //os_printf("cksum is %04x\n", ff.fc.crc);
   // write primary with incorrect seq
-  fc.seq = 0xffffffff;
-  fc.crc = FLASH_MAGIC;
-  if (spi_flash_write(addr, (void *)&fc, sizeof(FlashConfig)) != SPI_FLASH_RESULT_OK)
+  ff.fc.seq = 0xffffffff;
+  if (spi_flash_write(addr, (void *)&ff, sizeof(ff)) != SPI_FLASH_RESULT_OK)
     return false; // no harm done, give up
   // fill in correct seq
-  fc.seq = seq;
-  if (spi_flash_write(addr, (void *)&fc, sizeof(uint32_t)) != SPI_FLASH_RESULT_OK)
+  ff.fc.seq = seq;
+  if (spi_flash_write(addr, (void *)&ff, sizeof(uint32_t)) != SPI_FLASH_RESULT_OK)
     return false; // most likely failed, but no harm if successful
   // now that we have safely written the new version, erase old primary
   addr = FLASH_ADDR + flash_pri*FLASH_SECT;
@@ -44,11 +71,11 @@ bool ICACHE_FLASH_ATTR configSave(void) {
   if (spi_flash_erase_sector(addr>>12) != SPI_FLASH_RESULT_OK)
     return true; // no back-up but we're OK
   // write secondary
-  fc.seq = 0xffffffff;
-  if (spi_flash_write(addr, (void *)&fc, sizeof(FlashConfig)) != SPI_FLASH_RESULT_OK)
+  ff.fc.seq = 0xffffffff;
+  if (spi_flash_write(addr, (void *)&ff, sizeof(ff)) != SPI_FLASH_RESULT_OK)
     return true; // no back-up but we're OK
-  fc.seq = seq;
-  spi_flash_write(addr, (void *)&fc, sizeof(uint32_t));
+  ff.fc.seq = seq;
+  spi_flash_write(addr, (void *)&ff, sizeof(uint32_t));
   return true;
 }
 
@@ -57,17 +84,17 @@ void ICACHE_FLASH_ATTR configWipe(void) {
   spi_flash_erase_sector((FLASH_ADDR+FLASH_SECT)>>12);
 }
 
-static uint32_t ICACHE_FLASH_ATTR selectPrimary(FlashConfig *fc0, FlashConfig *fc1);
+static uint32_t ICACHE_FLASH_ATTR selectPrimary(FlashFull *fc0, FlashFull *fc1);
 
 bool ICACHE_FLASH_ATTR configRestore(void) {
-  FlashConfig fc0, fc1;
+  FlashFull ff0, ff1;
   // read both flash sectors
-  if (spi_flash_read(FLASH_ADDR, (void *)&fc0, sizeof(FlashConfig)) != SPI_FLASH_RESULT_OK)
-    memset(&fc0, sizeof(FlashConfig), 0); // clear in case of error
-  if (spi_flash_read(FLASH_ADDR+FLASH_SECT, (void *)&fc1, sizeof(FlashConfig)) != SPI_FLASH_RESULT_OK)
-    memset(&fc1, sizeof(FlashConfig), 0); // clear in case of error
+  if (spi_flash_read(FLASH_ADDR, (void *)&ff0, sizeof(ff0)) != SPI_FLASH_RESULT_OK)
+    memset(&ff0, 0, sizeof(ff0)); // clear in case of error
+  if (spi_flash_read(FLASH_ADDR+FLASH_SECT, (void *)&ff1, sizeof(ff1)) != SPI_FLASH_RESULT_OK)
+    memset(&ff1, 0, sizeof(ff1)); // clear in case of error
   // figure out which one is good
-  flash_pri = selectPrimary(&fc0, &fc1);
+  flash_pri = selectPrimary(&ff0, &ff1);
   // if neither is OK, we revert to defaults
   if (flash_pri < 0) {
     memcpy(&flashConfig, &flashDefault, sizeof(FlashConfig));
@@ -75,18 +102,27 @@ bool ICACHE_FLASH_ATTR configRestore(void) {
     return false;
   }
   // copy good one into global var and return
-  memcpy(&flashConfig, flash_pri == 0 ? &fc0 : &fc1, sizeof(FlashConfig));
+  memcpy(&flashConfig, flash_pri == 0 ? &ff0.fc : &ff1.fc, sizeof(FlashConfig));
   return true;
 }
 
-static uint32_t ICACHE_FLASH_ATTR selectPrimary(FlashConfig *fc0, FlashConfig *fc1) {
-  bool fc0_crc_ok = fc0->crc == FLASH_MAGIC && fc0->seq != 0xffffffff; // need real crc checksum...
-  bool fc1_crc_ok = fc1->crc == FLASH_MAGIC && fc1->seq != 0xffffffff; // need real crc checksum...
-  if (fc0_crc_ok)
-    if (!fc1_crc_ok || fc0->seq >= fc1->seq)
+static uint32_t ICACHE_FLASH_ATTR selectPrimary(FlashFull *ff0, FlashFull *ff1) {
+  // check CRC of ff0
+  uint16_t crc = ff0->fc.crc;
+  ff0->fc.crc = 0;
+  bool ff0_crc_ok = inet_chksum(ff0, sizeof(FlashFull)) == crc;
+
+  // check CRC of ff1
+  crc = ff1->fc.crc;
+  ff1->fc.crc = 0;
+  bool ff1_crc_ok = inet_chksum(ff1, sizeof(FlashFull)) == crc;
+
+  // decided which we like better
+  if (ff0_crc_ok)
+    if (!ff1_crc_ok || ff0->fc.seq >= ff1->fc.seq)
       return 0; // use first sector as primary
     else
       return 1; // second sector is newer
   else
-    return fc1_crc_ok ? 1 : -1;
+    return ff1_crc_ok ? 1 : -1;
 }
diff --git a/user/config.h b/user/config.h
index 1ec4400..c326a37 100644
--- a/user/config.h
+++ b/user/config.h
@@ -3,11 +3,12 @@
 
 typedef struct {
   uint32_t seq; // flash write sequence number
-  uint32_t crc; // FlashConfig crc
+  uint16_t magic, crc;
   int8_t   reset_pin, isp_pin, conn_led_pin, ser_led_pin;
   int32_t  baud_rate;
   char     hostname[32];               // if using DHCP
   uint32_t staticip, netmask, gateway; // using DHCP if staticip==0
+  uint8_t  log_mode;                   // UART log debug mode
 } FlashConfig;
 extern FlashConfig flashConfig;
 
diff --git a/user/log.c b/user/log.c
index 953e614..cb7a683 100644
--- a/user/log.c
+++ b/user/log.c
@@ -3,6 +3,7 @@
 #include 
 #include "uart.h"
 #include "cgi.h"
+#include "config.h"
 #include "log.h"
 
 // Web log for the esp8266 to replace outputting to uart1.
@@ -17,15 +18,19 @@ static int log_pos;
 static bool log_no_uart; // start out printing to uart
 static bool log_newline; // at start of a new line
 
+// called from wifi reset timer to turn UART on when we loose wifi and back off
+// when we connect to wifi AP. Here this is gated by the flash setting
 void ICACHE_FLASH_ATTR
 log_uart(bool enable) {
-	if (!enable && !log_no_uart) {
+	if (!enable && !log_no_uart && flashConfig.log_mode != LOG_MODE_ON) {
+		// we're asked to turn uart off, and uart is on, and the flash setting isn't always-on
 #if 1
 		os_printf("Turning OFF uart log\n");
 		os_delay_us(4*1000L); // time for uart to flush
 		log_no_uart = !enable;
 #endif
-	} else if (enable && log_no_uart) {
+	} else if (enable && log_no_uart && flashConfig.log_mode != LOG_MODE_OFF) {
+		// we're asked to turn uart on, and uart is off, and the flash setting isn't always-off
 		log_no_uart = !enable;
 		os_printf("Turning ON uart log\n");
 	}
@@ -119,7 +124,36 @@ ajaxLog(HttpdConnData *connData) {
 	return HTTPD_CGI_DONE;
 }
 
+static char *dbg_mode[] = { "auto", "off", "on" };
+
+int ICACHE_FLASH_ATTR
+ajaxLogDbg(HttpdConnData *connData) {
+	char buff[512];
+	int len, status = 400;
+	len = httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff));
+	if (len > 0) {
+		int8_t mode = -1;
+		if (os_strcmp(buff, "auto") == 0) mode = LOG_MODE_AUTO;
+		if (os_strcmp(buff, "off") == 0)  mode = LOG_MODE_OFF;
+		if (os_strcmp(buff, "on") == 0)   mode = LOG_MODE_ON;
+		if (mode >= 0) {
+			flashConfig.log_mode = mode;
+			if (mode != LOG_MODE_AUTO) log_uart(mode == LOG_MODE_ON);
+			status = configSave() ? 200 : 400;
+		}
+	} else if (connData->requestType == HTTPD_METHOD_GET) {
+		status = 200;
+	}
+
+	jsonHeader(connData, status);
+	os_sprintf(buff, "{\"mode\": \"%s\"}", dbg_mode[flashConfig.log_mode]);
+	httpdSend(connData, buff, -1);
+	return HTTPD_CGI_DONE;
+}
+
+
 void ICACHE_FLASH_ATTR logInit() {
+	log_no_uart = flashConfig.log_mode == LOG_MODE_OFF; // ON unless set to always-off
 	log_wr = 0;
 	log_rd = 0;
   os_install_putc1((void *)log_write_char);
diff --git a/user/log.h b/user/log.h
index 08330f8..94d52c0 100644
--- a/user/log.h
+++ b/user/log.h
@@ -3,8 +3,13 @@
 
 #include "httpd.h"
 
+#define LOG_MODE_AUTO 0
+#define LOG_MODE_OFF  1
+#define LOG_MODE_ON   2
+
 void logInit(void);
-void ICACHE_FLASH_ATTR log_uart(bool enable);
-int ICACHE_FLASH_ATTR ajaxLog(HttpdConnData *connData);
+void log_uart(bool enable);
+int ajaxLog(HttpdConnData *connData);
+int ajaxLogDbg(HttpdConnData *connData);
 
 #endif
diff --git a/user/user_main.c b/user/user_main.c
index 58f940a..57443ae 100644
--- a/user/user_main.c
+++ b/user/user_main.c
@@ -67,6 +67,7 @@ HttpdBuiltInUrl builtInUrls[]={
 	//{"/home.html", cgiEspFsHtml, NULL},
 	//{"/log.html", cgiEspFsHtml, NULL},
 	{"/log/text", ajaxLog, NULL},
+	{"/log/dbg", ajaxLogDbg, NULL},
 	//{"/console.html", cgiEspFsHtml, NULL},
 	{"/console/reset", ajaxConsoleReset, NULL},
 	{"/console/baud", ajaxConsoleBaud, NULL},