瀏覽代碼

fwupdate: wait for final messages in flashesp; try better error handling

Stick around for long enough that the final messages can be printed
when flashing over the serial port.

Try to be better about error recovery in the tty code. Still locks up
over USB, though...
H. Peter Anvin 2 年之前
父節點
當前提交
0955b6144c
共有 7 個文件被更改,包括 75 次插入24 次删除
  1. 27 10
      esp32/flashesp.pl
  2. 1 1
      esp32/max80/max80.ino
  3. 37 8
      esp32/max80/tty.cpp
  4. 10 5
      esp32/max80/tty.h
  5. 二進制
      esp32/output/max80.ino.bin
  6. 二進制
      fpga/output/v1.fw
  7. 二進制
      fpga/output/v2.fw

+ 27 - 10
esp32/flashesp.pl

@@ -7,6 +7,7 @@ use File::Temp;
 use File::Spec;
 use Time::HiRes qw(usleep tv_interval);
 use Digest::CRC qw(crc32);
+use v5.10;			# For "state"
 
 my $esptool = ($^O eq 'MSWin32') ? 'esptool.exe' : 'esptool.py';
 $esptool = $ENV{'ESPTOOL'} || $esptool;
@@ -249,7 +250,14 @@ foreach my $o (sort grep (/^flash_/, keys %espopt)) {
 push(@espcmd, @espfiles);
 
 print STDERR join(' ', @espcmd), "\n";
-$err = system(@espcmd);
+my $retries = 4;
+my $err = 0;
+while ($retries--) {
+    # Sometimes esptool tanks out for no reason, with error 256
+    $err = system(@espcmd);
+    last if ($err != 256);
+    usleep(1000000);
+}
 if ($err == -1) {
     print STDERR "$0: $espcmd[0]: $!\n";
 } elsif ($err) {
@@ -282,22 +290,20 @@ $tty->error_msg(1);
 $tty->handshake('none');
 $tty->databits(8);
 $tty->baudrate(115200);
-$tty->parity('none');
 $tty->stopbits(1);
+$tty->parity('none');
+$tty->stty_istrip(0);
+$tty->stty_inpck(0);
 $tty->datatype('raw');
+$tty->stty_icanon(0);
+$tty->stty_opost(0);
 $tty->stty_ignbrk(0);
-#$tty->stty_brkint(0);
-$tty->stty_parmrk(0);
-$tty->stty_istrip(0);
 $tty->stty_inlcr(0);
 $tty->stty_igncr(0);
 $tty->stty_icrnl(0);
-$tty->stty_opost(0);
 $tty->stty_echo(0);
 $tty->stty_echonl(0);
-$tty->stty_icanon(0);
 $tty->stty_isig(0);
-#$tty->stty_iexten(0);
 $tty->read_char_time(0);
 $tty->write_settings;
 
@@ -314,12 +320,16 @@ if ($tty->can_modemlines && !($tty->modemlines & $tty->MS_CTS_ON)) {
 }
 
 sub tty_read {
+    state %old_timeout;
     my($tty,$bufref,$timeout) = @_;
     my $d = $$bufref;
 
     if ($d eq '') {
 	my $c;
-	$tty->read_const_time($timeout);
+	if (!defined($old_timeout{$tty}) || $timeout != $old_timeout{$tty}) {
+	    $tty->read_const_time($timeout);
+	    $old_timeout{$tty} = $timeout;
+	}
 	($c,$d) = $tty->read(256);
 	return '' if (!$c);
     }
@@ -466,8 +476,15 @@ while ($last_ack < $bytes) {
 }
 
 tty_write($tty, "\004");		# EOT
+
+# Final messages out
+while (1) {
+    my $d = tty_read($tty, \$ttybuf, 1000);
+    last if ($d eq '');
+    print STDERR $d;
+}
 $tty->close;
 
-print STDERR "$0: $port: firmware upload complete\n";
+print STDERR "\n$0: $port: firmware upload complete\n";
 
 exit 0;

+ 1 - 1
esp32/max80/max80.ino

@@ -167,7 +167,7 @@ static void dump_tasks(void)
 }
 
 void loop() {
-    if (0) {
+    if (1) {
 	printf("loop task: %s\n", pcTaskGetName(xTaskGetCurrentTaskHandle()));
 	printf("idle task: %s\n", pcTaskGetName(xTaskGetIdleTaskHandle()));
 	dump_tasks();

+ 37 - 8
esp32/max80/tty.cpp

@@ -44,11 +44,15 @@ void TTY::reset()
     rx.b64_bits = 0;
 }
 
+static void null_flush(void)
+{
+}
 
 TTY::TTY(Stream &port)
 {
     _port = &port;
     rx_sbuf = true ? xStreamBufferCreate(STREAMBUF_SIZE, 1) : NULL;
+    _flush = null_flush;
     reset();
 }
 
@@ -67,21 +71,31 @@ int TTY::rxdata(void *buf, size_t len)
 
     int rcv = 0;
     while (!rcv) {
-	if (tx_credits_reset) {
-	    // Drain input before WRST
-	    rcv = xStreamBufferReceive(rx_sbuf, buf, len, 0);
+	rcv = xStreamBufferReceive(rx_sbuf, buf, len, 0);
+	if (rcv)
+	    break;
 
-	    if (rcv)
-		break;
+	uint32_t now = millis();
+	if (now - last_rx > 500) {
+	    last_rx = now;
+	    tx_credits_reset = true;
+	}
 
+	if (tx_credits_reset) {
+	    // Drain input before WRST
+	    flush();
 	    if (port().write(WRST)) {
-		printf("[UPLD] Resetting window\n");
+		printf("[UPLD] Resetting window, last_ack = %u\n", rx.last_ack);
 		tx_credits_reset = false;
 		tx_credits = STREAMBUF_SIZE - BUF_SLACK;
 	    } else {
 		// Uhm... wait a tiny bit and then try again to sent WRST?
-		printf("[UPLD] Failed to reset window?!\n");
-		rcv = xStreamBufferReceive(rx_sbuf, buf, len, 10);
+		static bool failed_once = false;
+		if (!failed_once) {
+		    printf("[UPLD] Failed to reset window?!\n");
+		    failed_once = true;
+		}
+		rcv = xStreamBufferReceive(rx_sbuf, buf, len, 1);
 	    }
 	} else {
 	    while (tx_credits >= WGO_CHUNK && port().write(WGO))
@@ -181,6 +195,8 @@ void TTY::_onrx()
     int byte, data;
 
     while ((byte = port().read()) >= 0) {
+	last_rx = millis();
+
 	switch (rx.state) {
 	case rx_state::normal:
 	    if (rx.rlen < sizeof fwupload_start &&
@@ -398,17 +414,30 @@ void TTY::uart_onerr(hardwareSerial_error_t err)
     }
 }
 
+static void uart_flush()
+{
+    Serial0.flush(true);
+}
+
+static void usb_flush()
+{
+    Serial.flush();
+}
+
 void TTY::init()
 {
     enq_str[sizeof(enq_str)-5] += max80_board_version;
 
     uart_tty = new TTY(Serial0);
+    uart_tty->_flush = uart_flush;
     Serial0.begin(BAUD_RATE);
     Serial0.onReceive(uart_onrx, false);
     Serial0.onReceiveError(uart_onerr);
 
     usb_tty  = new TTY(Serial);
+    usb_tty->_flush = usb_flush;
     Serial.onEvent(usb_onevent);
+    Serial.enableReboot(true);
 }
 
 void TTY::ping()

+ 10 - 5
esp32/max80/tty.h

@@ -25,29 +25,33 @@ struct tty_packet_hdr {
 } __attribute__((packed));
 
 class TTY {
-private:
-    Stream *_port;		// Android stream
-
 public:
     TTY(Stream &port);
     ~TTY();
     void reset();
     int  rxdata(void *buf, size_t len);
     static int rxdata(token_t me, void *buf, size_t len);
-    inline Stream & port() { return *_port; }
-    inline operator Stream & () { return port(); }
 
     // Global events
     static void init();
     static void ping();
 
 private:
+    Stream *_port;		// Android stream
+
     void _onrx();
     void _onerr();
     void _onbreak();
     void _onconnect();
     void _ondisconnect();
+    void (*_flush)();
+
+public:
+    inline void flush() { _flush(); }
+    inline Stream & port() { return *_port; }
+    inline operator Stream & () { return port(); }
 
+private:
     // Event handler dispatchers
     static void usb_onevent(void *arg, esp_event_base_t event_base,
 			    int32_t event_id, void *event_data);
@@ -80,5 +84,6 @@ private:
     StreamBufferHandle_t rx_sbuf;
     uint32_t tx_credits;
     volatile bool tx_credits_reset;
+    volatile uint32_t last_rx;
     uint8_t rx_data[256];
 };

二進制
esp32/output/max80.ino.bin


二進制
fpga/output/v1.fw


二進制
fpga/output/v2.fw