--- a/eric6/MicroPython/EspDevices.py Sat Dec 07 14:16:25 2019 +0100 +++ b/eric6/MicroPython/EspDevices.py Wed Jan 01 12:01:54 2020 +0100 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de> +# Copyright (c) 2019 - 2020 Detlev Offenbach <detlev@die-offenbachs.de> # """ @@ -11,7 +11,7 @@ import sys -from PyQt5.QtCore import pyqtSlot +from PyQt5.QtCore import pyqtSlot, QProcess from PyQt5.QtWidgets import QDialog from E5Gui import E5MessageBox @@ -24,16 +24,6 @@ import Preferences -# TODO: add backupFlash: python ./esptool.py --port /dev/ttyUSB4 --baud 115200 read_flash 0x00000 0x400000 backup.img -# selection of sizes: 1MB, 2MB, 4MB, 8MB, 16M (0x100000, 0x200000, 0x400000, 0x800000, 0x1000000) -# ESP8266: 256KB, 512KB (0x40000, 0x80000) -# TODO: add restoreFlash: python esptool.py --port /dev/ttyUSB4 write_flash --flash_mode qio 0x00000 backup.img -# alternative modes for --flash_mode: qio,qout,dio,dout -# optional: --flash_size 1MB, 2MB, 4MB, 8MB, 16M (ESP8266 zusätzlich 256KB, 512KB) -# TODO: add showChipID: python esptool.py --port /dev/ttyUSB4 --baud 115200 chip_id -# TODO: add showFlashID: python esptool.py --port /dev/ttyUSB4 --baud 115200 flash_id -# TODO: add readMAC: python esptool.py --port /dev/ttyUSB4 --baud 115200 read_mac - class EspDevice(MicroPythonDevice): """ Class implementing the device for ESP32 and ESP8266 based boards. @@ -146,6 +136,23 @@ self.__flashAddons) act.setEnabled(not connected) menu.addSeparator() + act = menu.addAction(self.tr("Backup Firmware"), + self.__backupFlash) + act.setEnabled(not connected) + act = menu.addAction(self.tr("Restore Firmware"), + self.__restoreFlash) + act.setEnabled(not connected) + menu.addSeparator() + act = menu.addAction(self.tr("Show Chip ID"), + self.__showChipID) + act.setEnabled(not connected) + act = menu.addAction(self.tr("Show Flash ID"), + self.__showFlashID) + act.setEnabled(not connected) + act = menu.addAction(self.tr("Show MAC Address"), + self.__showMACAddress) + act.setEnabled(not connected) + menu.addSeparator() act = menu.addAction(self.tr("Reset Device"), self.__resetDevice) menu.addSeparator() menu.addAction(self.tr("Install 'esptool.py'"), self.__installEspTool) @@ -168,7 +175,8 @@ "erase_flash", ] dlg = E5ProcessDialog(self.tr("'esptool erase_flash' Output"), - self.tr("Erase Flash")) + self.tr("Erase Flash"), + showProgress=True) res = dlg.startProcess(sys.executable, flashArgs) if res: dlg.exec_() @@ -201,7 +209,8 @@ firmware, ] dlg = E5ProcessDialog(self.tr("'esptool write_flash' Output"), - self.tr("Flash MicroPython Firmware")) + self.tr("Flash MicroPython Firmware"), + showProgress=True) res = dlg.startProcess(sys.executable, flashArgs) if res: dlg.exec_() @@ -225,20 +234,148 @@ firmware, ] dlg = E5ProcessDialog(self.tr("'esptool write_flash' Output"), - self.tr("Flash Additional Firmware")) + self.tr("Flash Additional Firmware"), + showProgress=True) + res = dlg.startProcess(sys.executable, flashArgs) + if res: + dlg.exec_() + + @pyqtSlot() + def __backupFlash(self): + """ + Private slot to backup the currently flashed firmware. + """ + from .EspBackupRestoreFirmwareDialog import ( + EspBackupRestoreFirmwareDialog + ) + dlg = EspBackupRestoreFirmwareDialog(backupMode=True) + if dlg.exec_() == QDialog.Accepted: + chip, flashSize, flashMode, firmware = dlg.getData() + flashArgs = [ + "-u", + "-m", "esptool", + "--chip", chip, + "--port", self.microPython.getCurrentPort(), + "read_flash", + "0x0", flashSize, + firmware, + ] + dlg = E5ProcessDialog(self.tr("'esptool read_flash' Output"), + self.tr("Backup Firmware"), + showProgress=True) res = dlg.startProcess(sys.executable, flashArgs) if res: dlg.exec_() @pyqtSlot() + def __restoreFlash(self): + """ + Private slot to restore a previously saved firmware. + """ + from .EspBackupRestoreFirmwareDialog import ( + EspBackupRestoreFirmwareDialog + ) + dlg = EspBackupRestoreFirmwareDialog(backupMode=False) + if dlg.exec_() == QDialog.Accepted: + chip, flashSize, flashMode, firmware = dlg.getData() + flashArgs = [ + "-u", + "-m", "esptool", + "--chip", chip, + "--port", self.microPython.getCurrentPort(), + "write_flash", + "--flash_mode", flashMode, + ] + if bool(flashSize): + flashArgs.extend([ + "--flash_size", flashSize, + ]) + flashArgs.extend([ + "0x0", + firmware, + ]) + dlg = E5ProcessDialog(self.tr("'esptool write_flash' Output"), + self.tr("Restore Firmware"), + showProgress=True) + res = dlg.startProcess(sys.executable, flashArgs) + if res: + dlg.exec_() + + @pyqtSlot() + def __showChipID(self): + """ + Private slot to show the ID of the ESP chip. + """ + args = [ + "-u", + "-m", "esptool", + "--port", self.microPython.getCurrentPort(), + "chip_id" + ] + dlg = E5ProcessDialog(self.tr("'esptool chip_id' Output"), + self.tr("Show Chip ID")) + res = dlg.startProcess(sys.executable, args) + if res: + dlg.exec_() + + @pyqtSlot() + def __showFlashID(self): + """ + Private slot to show the ID of the ESP flash chip. + """ + args = [ + "-u", + "-m", "esptool", + "--port", self.microPython.getCurrentPort(), + "flash_id" + ] + dlg = E5ProcessDialog(self.tr("'esptool flash_id' Output"), + self.tr("Show Flash ID")) + res = dlg.startProcess(sys.executable, args) + if res: + dlg.exec_() + + @pyqtSlot() + def __showMACAddress(self): + """ + Private slot to show the MAC address of the ESP chip. + """ + args = [ + "-u", + "-m", "esptool", + "--port", self.microPython.getCurrentPort(), + "read_mac" + ] + dlg = E5ProcessDialog(self.tr("'esptool read_mac' Output"), + self.tr("Show MAC Address")) + res = dlg.startProcess(sys.executable, args) + if res: + dlg.exec_() + + @pyqtSlot() def __resetDevice(self): """ Private slot to reset the connected device. """ - self.microPython.commandsInterface().execute([ - "import machine", - "machine.reset()", - ]) + if self.microPython.isConnected(): + self.microPython.commandsInterface().execute([ + "import machine", + "machine.reset()", + ]) + else: + # perform a reset via esptool using flash_id command ignoring + # the output + args = [ + "-u", + "-m", "esptool", + "--port", self.microPython.getCurrentPort(), + "flash_id" + ] + proc = QProcess() + proc.start(sys.executable, args) + procStarted = proc.waitForStarted(10000) + if procStarted: + proc.waitForFinished(10000) @pyqtSlot() def __installEspTool(self):