Browse Source

Update FPGA board_info at flash time if from ESP

When flashing from ESP via either http or serial port, flash the FPGA
board_info at flashing time instead of waiting for the FPGA to come
online to sync it. This is currently not an issue, but could become
one in the future if RV32 initialization requires board specific
knowledge.

Clean up the upload options in the Makefile.

Move esp32/flashesp.pl to tools/flashmax.pl.
H. Peter Anvin 2 years ago
parent
commit
5068ef35af
9 changed files with 100 additions and 22 deletions
  1. 43 12
      Makefile
  2. 36 1
      esp32/max80/fwupdate.c
  3. 18 8
      esp32/max80/spiflash.c
  4. 3 1
      esp32/max80/spiflash.h
  5. BIN
      esp32/output/max80.ino.bin
  6. BIN
      fpga/output/max80.fw
  7. BIN
      fpga/output/v1.fw
  8. BIN
      fpga/output/v2.fw
  9. 0 0
      tools/flashmax.pl

+ 43 - 12
Makefile

@@ -11,7 +11,9 @@ MAX80_IP  ?= max80
 
 CURL	   = curl
 PERL	   = perl
-ESPTOOL   ?= esptool
+PYTHON     = python
+ESPTOOL   ?= esptool.py
+export ESPTOOL
 
 all clean spotless :
 	$(MAKE) local.$@ $(SUBDIRS) goal=$@
@@ -71,25 +73,54 @@ program flash:
 program-% flash-%: prefpga
 	$(MAKE) -C fpga $@
 
-# ESP update by USB or serial port
+# ESP update by USB or serial port using esptool directly
 upload-esp:
 	$(MAKE) -C esp32 upload
 
-# Update via HTTP or serial port
 ip = $(MAX80_IP)
+
+ifeq ($(PORT),)
+# --- Upload via HTTP ---
+
+# Generic upload for newer firmware
+upload:
+	@echo 'NOT IMPLEMENTED YET, should be:'
+	@echo '$(CURL) -v --data-binary @fpga/output/$(PROJECT).fw http://$(ip)/sys/fwupdate'
+	@exit 1
+
+# Version-specific uploads for older firmware
 upload-v%:
-	if [ -z '$(PORT)' ]; then \
-		$(CURL) -v --data-binary @fpga/output/v$*.fw http://$(ip)/sys/fwupdate ; \
-	else \
-		$(PERL) ./esp32/flashesp.pl fpga/output/v$*.fw '$(PORT)' $(FLASHOPT); \
-	fi
+	$(CURL) -v --data-binary @fpga/output/v$*.fw 'http://$(ip)/sys/fwupdate'
+
+# setver is not supported via HTTP
+setver-v%:
+	@echo 'make $@ requires PORT= to be specified'
+	@exit 1
+
+else
+# --- Upload via serial port/USB
 
-# Set board revision in flash
-WRITEFLASH = [ ! -z '$(PORT)' ] && $(ESPTOOL) --before default_reset --after hard_reset --port $(PORT) write_flash -z
+# Generic upload for newer firmware
+upload:
+	@echo 'NOT IMPLEMENTED YET, should be:'
+	@echo '$(PERL) ./tools/flashmax.pl fpga/output/$(PROJECT).fw $(PORT) $(FLASHOPT)'
+	@exit 1
+
+# Version-specific uploads for older firmware
+upload-v%:
+	$(PERL) ./tools/flashmax.pl fpga/output/v$*.fw '$(PORT)' $(FLASHOPT)
+
+# Write board ID/revision to flash
+WRITEFLASH = $(ESPTOOL) --before default_reset --after hard_reset --port '$(PORT)' write_flash -z
 
 stamp_max80_v%.bin:
 	$(PERL) -e '$$m = "MAX80 v$*\0"; print $$m, "\xff" x (4096 - length ($$m));' > $@
 
+# esptool is unreliable, so retry several times with a brief break in between
 setver-v%: stamp_max80_v%.bin
-	if [ -z '$(PORT)' ]; then echo 'Set PORT for this command' 2>&1; exit 1; fi
-	$(WRITEFLASH) 0 $< || sleep 1; $(WRITEFLASH) 0 $<
+	for i in `seq 1 5`; do \
+		$(WRITEFLASH) 0 $< && break; \
+		sleep 1; \
+	done
+
+endif

+ 36 - 1
esp32/max80/fwupdate.c

@@ -9,6 +9,7 @@
 #include "spz.h"
 #include "httpd.h"
 #include "fw.h"
+#include "boardinfo_esp.h"
 
 #include <unzipLIB.h>
 #include <zlib.h>
@@ -256,6 +257,33 @@ static int fwupdate_skip_chunk(spz_stream *spz)
     return 0;
 }
 
+static int fwupdate_boardinfo(spz_stream *spz)
+{
+    uint8_t *board_info_data = spz_malloc(spz, BOARDINFO_SIZE);
+    int rv = Z_OK;
+
+    MSG("updating FPGA board_info\n");
+
+    if (!board_info_data)
+	return spz->err;
+
+    if (board_info.len >= 16 &&
+	board_info.len <= sizeof board_info &&
+	board_info.len <= BOARDINFO_SIZE) {
+	memcpy(board_info_data, &board_info, board_info.len);
+	memset(board_info_data + board_info.len, 0xff,
+	       BOARDINFO_SIZE - board_info.len);
+
+	rv = spiflash_write_spz(spz, board_info_data, BOARDINFO_SIZE);
+    }
+
+    free(board_info_data);
+    fwupdate_skip_chunk(spz);
+    if (rv)
+	spz->err = rv;
+    return spz->err;
+}
+
 /* Process a data chunk; return a nonzero value if done */
 static int fwupdate_process_chunk(spz_stream *spz)
 {
@@ -280,7 +308,9 @@ static int fwupdate_process_chunk(spz_stream *spz)
 	return Z_STREAM_END;	/* End of data - not an error */
     case FDT_DATA:
 	MSG("updating FPGA flash\n");
-	return spiflash_write_spz(spz);
+	return spiflash_write_spz(spz, NULL, 0);
+    case FDT_BOARDINFO:
+	return fwupdate_boardinfo(spz);
     case FDT_TARGET:
 	str = fwupdate_read_chunk_str(spz);
 #if 0
@@ -310,6 +340,11 @@ static int fwupdate_process_chunk(spz_stream *spz)
 	rv = fpga_program_spz(spz);
 	CMSG("done\n");
 	return rv;
+    case FDT_ESP_PART:
+    case FDT_ESP_SYS:
+    case FDT_ESP_TOOL:
+	/* Not applicable to this update method */
+	return fwupdate_skip_chunk(spz);
     default:
 	if (spz->header.flags & FDF_OPTIONAL) {
 	    return fwupdate_skip_chunk(spz);

+ 18 - 8
esp32/max80/spiflash.c

@@ -338,11 +338,16 @@ static void spiflash_show_status(void)
 #define PIN_FPGA_READY		9
 #define PIN_FPGA_BOARD_ID	1
 
-int spiflash_write_spz(spz_stream *spz)
+/* Set data and data_len if the data to be written is not from the spz */
+int spiflash_write_spz(spz_stream *spz,
+		       const void *data, unsigned int data_left)
 {
-    unsigned int data_left = spz->header.len;
-    unsigned int addr      = spz->header.addr;
     esp_err_t rv;
+    const uint8_t *dptr = data;
+    unsigned int addr   = spz->header.addr;
+
+    if (!dptr)
+	data_left = spz->header.len;
 
     if (!data_left || spz->err)
 	return spz->err;
@@ -392,11 +397,16 @@ int spiflash_write_spz(spz_stream *spz)
 		   spz->vbuf+SPIFLASH_SECTOR_SIZE-post_padding,
 		   post_padding);
 
-	rv = spz_read_data(spz, spz->dbuf+pre_padding, bytes);
-	if (rv != (int)bytes) {
-	    MSG("needed %u bytes got %d\n", bytes, rv);
-	    rv = Z_DATA_ERROR;
-	    goto err;
+	if (dptr) {
+	    memcpy(spz->dbuf+pre_padding, dptr, bytes);
+	    dptr += bytes;
+	} else {
+	    rv = spz_read_data(spz, spz->dbuf+pre_padding, bytes);
+	    if (rv != (int)bytes) {
+		MSG("needed %u bytes got %d\n", bytes, rv);
+		rv = Z_DATA_ERROR;
+		goto err;
+	    }
 	}
 
 	rv = spiflash_write_sector(spz, addr);

+ 3 - 1
esp32/max80/spiflash.h

@@ -8,7 +8,9 @@
 struct spz_stream;
 typedef struct spz_stream spz_stream;
 
-extern_c int spiflash_write_spz(spz_stream *spz);
+/* Set data and data_len if the data to be written is not from the spz */
+extern_c int spiflash_write_spz(spz_stream *spz,
+				const void *data, unsigned int data_len);
 
 /* SPI flash command opcodes */
 enum romcmd {

BIN
esp32/output/max80.ino.bin


BIN
fpga/output/max80.fw


BIN
fpga/output/v1.fw


BIN
fpga/output/v2.fw


+ 0 - 0
esp32/flashesp.pl → tools/flashmax.pl