add UART debug log control UI

pull/30/head
Thorsten von Eicken 10 years ago
parent 62e6839788
commit c570a31751
  1. 37
      html/console.js
  2. 25
      html/log.html
  3. 5
      html/style.css
  4. 25
      html/ui.js
  5. 1
      serial/console.c
  6. 92
      user/config.c
  7. 3
      user/config.h
  8. 38
      user/log.c
  9. 9
      user/log.h
  10. 1
      user/user_main.c

@ -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(
' <a id="'+baud+'-button" href="#" class="pure-button">'+baud+'</a>'));
$("#"+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");
}
}

@ -4,15 +4,17 @@
</div>
<div class="content">
<p>The debug log shows the most recent characters printed by the esp-link software itself to
its own debug log.</p>
<div class="pure-g">
<div class="pure-u-1-4">
<p style="padding-top: 0.4em;">
<p class="pure-u-1-4">
<a id="refresh-button" class="pure-button button-primary" href="#">Refresh</a>
</p>
</div>
<p class="pure-u-3-4">
The debug log shows the most recent characters printed by the esp-link software itself to
its own debug log.
<p class="pure-u-3-4" style="vertical-align: baseline">
UART debug log:
<a id="dbg-auto" class="dbg-btn pure-button" href="#">auto</a>
<a id="dbg-off" class="dbg-btn pure-button" href="#">off</a>
<a id="dbg-on" class="dbg-btn pure-button" href="#">on</a>
</p>
</div>
<pre id="console" class="console" style="margin-top: 0px;"></pre>
@ -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() {});
});
</script>
</body></html>

@ -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;

@ -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(
' <a id="'+baud+'-button" href="#" class="pure-button">'+baud+'</a>'));
$("#"+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) {

@ -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;

@ -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<len; i++) {
os_printf("0x%02x", ((uint8_t *)addr)[i]);
}
os_printf("\n");
}
#endif
bool ICACHE_FLASH_ATTR configSave(void) {
FlashConfig fc;
memcpy(&fc, &flashConfig, sizeof(FlashConfig));
uint32_t seq = fc.seq+1;
FlashFull ff;
memset(&ff, 0, sizeof(ff));
memcpy(&ff, &flashConfig, sizeof(FlashConfig));
uint32_t seq = ff.fc.seq+1;
// erase secondary
uint32_t addr = FLASH_ADDR + (1-flash_pri)*FLASH_SECT;
if (spi_flash_erase_sector(addr>>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;
}

@ -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;

@ -3,6 +3,7 @@
#include <esp8266.h>
#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);

@ -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

@ -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},

Loading…
Cancel
Save