reorganize flash tool
This commit is contained in:
parent
d0018c6726
commit
f12d6267b4
|
@ -0,0 +1,124 @@
|
|||
|
||||
import flashtool.esptool as esptool
|
||||
import os
|
||||
from flashtool.version import VERSION
|
||||
|
||||
class Flasher():
|
||||
def getVersion(self):
|
||||
return ("Version %s, esptool %s"%(VERSION,str(esptool.__version__)))
|
||||
|
||||
UPDATE_ADDR = 0x10000
|
||||
HDROFFSET = 288
|
||||
VERSIONOFFSET = 16
|
||||
NAMEOFFSET = 48
|
||||
IDOFFSET=12 #2 byte chipid
|
||||
MINSIZE = HDROFFSET + NAMEOFFSET + 32
|
||||
CHECKBYTES = {
|
||||
288: 0x32, # app header magic
|
||||
289: 0x54,
|
||||
290: 0xcd,
|
||||
291: 0xab
|
||||
}
|
||||
#flash addresses for full images based on chip id
|
||||
FLASH_ADDR={
|
||||
0: 0x1000,
|
||||
9: 0
|
||||
}
|
||||
def getString(self,buffer, offset, len):
|
||||
return buffer[offset:offset + len].rstrip(b'\0').decode('utf-8')
|
||||
def getFirmwareInfo(self,filename,isFull):
|
||||
with open(filename,"rb") as ih:
|
||||
buffer = ih.read(self.MINSIZE)
|
||||
if len(buffer) != self.MINSIZE:
|
||||
return self.setErr("invalid image file %s, to short"%filename)
|
||||
if buffer[0] != 0xe9:
|
||||
return self.setErr("invalid magic in file, expected 0xe9 got 0x%02x"%buffer[0])
|
||||
chipid= buffer[self.IDOFFSET]+256*buffer[self.IDOFFSET+1]
|
||||
flashoffset=self.FLASH_ADDR.get(chipid)
|
||||
if flashoffset is None:
|
||||
return self.setErr("unknown chip id in image %d",chipid);
|
||||
if isFull:
|
||||
offset=self.UPDATE_ADDR-flashoffset;
|
||||
offset-=self.MINSIZE
|
||||
ih.seek(offset,os.SEEK_CUR)
|
||||
buffer=ih.read(self.MINSIZE)
|
||||
if len(buffer) != self.MINSIZE:
|
||||
return self.setErr("invalid image file %s, to short"%filename)
|
||||
if buffer[0] != 0xe9:
|
||||
return self.setErr("invalid magic in file, expected 0xe9 got 0x%02x"%buffer[0])
|
||||
for k, v in self.CHECKBYTES.items():
|
||||
if buffer[k] != v:
|
||||
return self.setErr("invalid magic at %d, expected %d got %d"
|
||||
% (k+offset, v, buffer[k]))
|
||||
name = self.getString(buffer, self.HDROFFSET + self.NAMEOFFSET, 32)
|
||||
version = self.getString(buffer, self.HDROFFSET + self.VERSIONOFFSET, 32)
|
||||
chipid= buffer[self.IDOFFSET]+256*buffer[self.IDOFFSET+1]
|
||||
flashoffset=flashoffset if isFull else self.UPDATE_ADDR
|
||||
return {
|
||||
'error':False,
|
||||
'info':"%s:%s"%(name,version),
|
||||
'chipid':chipid,
|
||||
'flashbase':flashoffset
|
||||
}
|
||||
def setErr(self,err):
|
||||
return {'error':True,'info':err}
|
||||
def checkImageFile(self,filename,isFull):
|
||||
if not os.path.exists(filename):
|
||||
return self.setErr("file %s not found"%filename)
|
||||
return self.getFirmwareInfo(filename,isFull)
|
||||
|
||||
def checkSettings(self,port,fileName,isFull):
|
||||
if port is None:
|
||||
print("ERROR: no com port selected")
|
||||
return
|
||||
if fileName is None or fileName == '':
|
||||
print("ERROR: no filename selected")
|
||||
return
|
||||
info = self.checkImageFile(fileName, isFull)
|
||||
if info['error']:
|
||||
print("ERROR: %s" % info['info'])
|
||||
return
|
||||
return {'fileName': fileName,'port':port,'isFull':isFull,'info':info}
|
||||
def runEspTool(self,command):
|
||||
print("run esptool: %s" % " ".join(command))
|
||||
try:
|
||||
esptool.main(command)
|
||||
print("esptool done")
|
||||
return True
|
||||
except Exception as e:
|
||||
print("Exception in esptool %s" % e)
|
||||
def verifyChip(self,param):
|
||||
if not param:
|
||||
print("check failed")
|
||||
return
|
||||
imageChipId=param['info']['chipid']
|
||||
chip=esptool.ESPLoader.detect_chip(param['port'])
|
||||
print("Detected chip %s, id=%d"%(chip.CHIP_NAME,chip.IMAGE_CHIP_ID))
|
||||
if (chip.IMAGE_CHIP_ID != imageChipId):
|
||||
print("##Error: chip id in image %d does not match detected chip"%imageChipId)
|
||||
return
|
||||
print("Checks OK")
|
||||
param['chipname']=chip.CHIP_NAME
|
||||
return param
|
||||
def runCheck(self,port,fileName,isFull):
|
||||
param = self.checkSettings(port,fileName,isFull)
|
||||
if not param:
|
||||
return
|
||||
print("Settings OK")
|
||||
param=self.verifyChip(param)
|
||||
if not param:
|
||||
print("Check Failed")
|
||||
return
|
||||
print("flashbase=0x%x"%param['info']['flashbase'])
|
||||
return param
|
||||
def runFlash(self,param):
|
||||
if not param:
|
||||
return
|
||||
if param['isFull']:
|
||||
command=['--chip',param['chipname'],'--port',param['port'],'write_flash',str(param['info']['flashbase']),param['fileName']]
|
||||
self.runEspTool(command)
|
||||
else:
|
||||
command=['--chip',param['chipname'],'--port',param['port'],'erase_region','0xe000','0x2000']
|
||||
self.runEspTool(command)
|
||||
command = ['--chip', param['chipname'], '--port', param['port'], 'write_flash', str(param['info']['flashbase']), param['fileName']]
|
||||
self.runEspTool(command)
|
|
@ -1,6 +1,38 @@
|
|||
#! /usr/bin/env python3
|
||||
import builtins
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import importlib.abc
|
||||
import importlib.util
|
||||
import types
|
||||
|
||||
|
||||
'''
|
||||
Inject a base package for our current directory
|
||||
'''
|
||||
class MyLoader(importlib.abc.InspectLoader):
|
||||
def is_package(self, fullname: str) -> bool:
|
||||
return True
|
||||
def get_source(self, fullname: str):
|
||||
return None
|
||||
def get_code(self, fullname: str):
|
||||
return ""
|
||||
class MyFinder(importlib.abc.MetaPathFinder):
|
||||
def __init__(self,baspkg,basedir=os.path.dirname(__file__),debug=False):
|
||||
self.pkg=baspkg
|
||||
self.dir=basedir
|
||||
self.debug=debug
|
||||
def find_spec(self,fullname, path, target=None):
|
||||
if fullname == self.pkg:
|
||||
if self.debug:
|
||||
print("F:matching %"%fullname)
|
||||
spec=importlib.util.spec_from_file_location(fullname, self.dir,loader=MyLoader(), submodule_search_locations=[self.dir])
|
||||
if self.debug:
|
||||
print("F:injecting:",spec)
|
||||
return spec
|
||||
sys.meta_path.insert(0,MyFinder('flashtool'))
|
||||
|
||||
|
||||
try:
|
||||
import serial
|
||||
|
@ -16,130 +48,8 @@ import tkinter.font as tkFont
|
|||
import os
|
||||
import serial.tools.list_ports
|
||||
from tkinter import filedialog as FileDialog
|
||||
from flashtool.flasher import Flasher
|
||||
|
||||
import builtins
|
||||
import esptool
|
||||
|
||||
VERSION="Version 2.0"
|
||||
class Flasher():
|
||||
def getVersion(self):
|
||||
return ("Version %s, esptool %s"%(VERSION,str(esptool.__version__)))
|
||||
|
||||
UPDATE_ADDR = 0x10000
|
||||
HDROFFSET = 288
|
||||
VERSIONOFFSET = 16
|
||||
NAMEOFFSET = 48
|
||||
IDOFFSET=12 #2 byte chipid
|
||||
MINSIZE = HDROFFSET + NAMEOFFSET + 32
|
||||
CHECKBYTES = {
|
||||
288: 0x32, # app header magic
|
||||
289: 0x54,
|
||||
290: 0xcd,
|
||||
291: 0xab
|
||||
}
|
||||
#flash addresses for full images based on chip id
|
||||
FLASH_ADDR={
|
||||
0: 0x1000,
|
||||
9: 0
|
||||
}
|
||||
def getString(self,buffer, offset, len):
|
||||
return buffer[offset:offset + len].rstrip(b'\0').decode('utf-8')
|
||||
def getFirmwareInfo(self,filename,isFull):
|
||||
with open(filename,"rb") as ih:
|
||||
buffer = ih.read(self.MINSIZE)
|
||||
if len(buffer) != self.MINSIZE:
|
||||
return self.setErr("invalid image file %s, to short"%filename)
|
||||
if buffer[0] != 0xe9:
|
||||
return self.setErr("invalid magic in file, expected 0xe9 got 0x%02x"%buffer[0])
|
||||
chipid= buffer[self.IDOFFSET]+256*buffer[self.IDOFFSET+1]
|
||||
flashoffset=self.FLASH_ADDR.get(chipid)
|
||||
if flashoffset is None:
|
||||
return self.setErr("unknown chip id in image %d",chipid);
|
||||
if isFull:
|
||||
offset=self.UPDATE_ADDR-flashoffset;
|
||||
offset-=self.MINSIZE
|
||||
ih.seek(offset,os.SEEK_CUR)
|
||||
buffer=ih.read(self.MINSIZE)
|
||||
if len(buffer) != self.MINSIZE:
|
||||
return self.setErr("invalid image file %s, to short"%filename)
|
||||
if buffer[0] != 0xe9:
|
||||
return self.setErr("invalid magic in file, expected 0xe9 got 0x%02x"%buffer[0])
|
||||
for k, v in self.CHECKBYTES.items():
|
||||
if buffer[k] != v:
|
||||
return self.setErr("invalid magic at %d, expected %d got %d"
|
||||
% (k+offset, v, buffer[k]))
|
||||
name = self.getString(buffer, self.HDROFFSET + self.NAMEOFFSET, 32)
|
||||
version = self.getString(buffer, self.HDROFFSET + self.VERSIONOFFSET, 32)
|
||||
chipid= buffer[self.IDOFFSET]+256*buffer[self.IDOFFSET+1]
|
||||
flashoffset=flashoffset if isFull else self.UPDATE_ADDR
|
||||
return {
|
||||
'error':False,
|
||||
'info':"%s:%s"%(name,version),
|
||||
'chipid':chipid,
|
||||
'flashbase':flashoffset
|
||||
}
|
||||
def setErr(self,err):
|
||||
return {'error':True,'info':err}
|
||||
def checkImageFile(self,filename,isFull):
|
||||
if not os.path.exists(filename):
|
||||
return self.setErr("file %s not found"%filename)
|
||||
return self.getFirmwareInfo(filename,isFull)
|
||||
|
||||
def checkSettings(self,port,fileName,isFull):
|
||||
if port is None:
|
||||
print("ERROR: no com port selected")
|
||||
return
|
||||
if fileName is None or fileName == '':
|
||||
print("ERROR: no filename selected")
|
||||
return
|
||||
info = self.checkImageFile(fileName, isFull)
|
||||
if info['error']:
|
||||
print("ERROR: %s" % info['info'])
|
||||
return
|
||||
return {'fileName': fileName,'port':port,'isFull':isFull,'info':info}
|
||||
def runEspTool(self,command):
|
||||
print("run esptool: %s" % " ".join(command))
|
||||
try:
|
||||
esptool.main(command)
|
||||
print("esptool done")
|
||||
return True
|
||||
except Exception as e:
|
||||
print("Exception in esptool %s" % e)
|
||||
def verifyChip(self,param):
|
||||
if not param:
|
||||
print("check failed")
|
||||
return
|
||||
imageChipId=param['info']['chipid']
|
||||
chip=esptool.ESPLoader.detect_chip(param['port'])
|
||||
print("Detected chip %s, id=%d"%(chip.CHIP_NAME,chip.IMAGE_CHIP_ID))
|
||||
if (chip.IMAGE_CHIP_ID != imageChipId):
|
||||
print("##Error: chip id in image %d does not match detected chip"%imageChipId)
|
||||
return
|
||||
print("Checks OK")
|
||||
param['chipname']=chip.CHIP_NAME
|
||||
return param
|
||||
def runCheck(self,port,fileName,isFull):
|
||||
param = self.checkSettings(port,fileName,isFull)
|
||||
if not param:
|
||||
return
|
||||
print("Settings OK")
|
||||
param=self.verifyChip(param)
|
||||
if not param:
|
||||
print("Check Failed")
|
||||
return
|
||||
print("flashbase=0x%x"%param['info']['flashbase'])
|
||||
return param
|
||||
def runFlash(self,param):
|
||||
if not param:
|
||||
return
|
||||
if param['isFull']:
|
||||
command=['--chip',param['chipname'],'--port',param['port'],'write_flash',str(param['info']['flashbase']),param['fileName']]
|
||||
self.runEspTool(command)
|
||||
else:
|
||||
command=['--chip',param['chipname'],'--port',param['port'],'erase_region','0xe000','0x2000']
|
||||
self.runEspTool(command)
|
||||
command = ['--chip', param['chipname'], '--port', param['port'], 'write_flash', str(param['info']['flashbase']), param['fileName']]
|
||||
self.runEspTool(command)
|
||||
|
||||
def main():
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
VERSION="2.1"
|
Loading…
Reference in New Issue