diff --git a/.gitignore b/.gitignore
index 5efc835..68504e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -202,4 +202,7 @@ local.properties
/Package/Firmware Installer Setup.exe
/Package/Firmware Installer-cache/
-.idea
\ No newline at end of file
+.Package/
+.DS_Store
+.idea/
+firmwareInstaller.bak.py
diff --git a/.idea/FirmwareInstaller.iml b/.idea/FirmwareInstaller.iml
deleted file mode 100644
index d0876a7..0000000
--- a/.idea/FirmwareInstaller.iml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 314edf0..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/Installer.spec b/Installer.spec
index d94b441..c028924 100644
--- a/Installer.spec
+++ b/Installer.spec
@@ -3,12 +3,14 @@
block_cipher = None
-
+binaries = [
+ ('C:\\Windows\\System32\\libusb0.dll', '.'),
+]
a = Analysis(['src\\firmwareInstaller.py'],
pathex=['D:\\Work\\Project\\FirmwareInstaller'],
- binaries=[],
+ binaries=binaries,
datas=[('src\\ico.ico', '.')],
- hiddenimports=[],
+ hiddenimports=['usb'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
diff --git a/Package/Firmware Installer.aip b/Package/Firmware Installer.aip
index 4585b9c..6dd08fd 100644
--- a/Package/Firmware Installer.aip
+++ b/Package/Firmware Installer.aip
@@ -1,9 +1,13 @@
-
+
+
+
+
+
@@ -14,10 +18,10 @@
-
+
-
+
@@ -34,42 +38,32 @@
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
@@ -82,80 +76,36 @@
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
@@ -163,416 +113,264 @@
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -592,117 +390,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -771,46 +458,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
+
+
@@ -830,7 +483,7 @@
-
+
@@ -847,9 +500,9 @@
-
+
-
+
@@ -858,28 +511,28 @@
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
@@ -901,7 +554,7 @@
-
+
@@ -936,7 +589,7 @@
-
+
@@ -971,7 +624,7 @@
-
+
@@ -1120,7 +773,7 @@
-
+
@@ -1149,10 +802,9 @@
-
-
+
-
+
@@ -1348,10 +1000,10 @@
-
+
-
+
@@ -1364,7 +1016,6 @@
-
@@ -1400,10 +1051,10 @@
-
+
-
+
@@ -1413,7 +1064,6 @@
-
@@ -1457,10 +1107,10 @@
-
+
-
+
@@ -1473,7 +1123,6 @@
-
@@ -1497,10 +1146,10 @@
-
+
-
+
@@ -1511,7 +1160,6 @@
-
@@ -1550,10 +1198,10 @@
-
+
-
+
@@ -1564,7 +1212,6 @@
-
@@ -1601,10 +1248,10 @@
-
+
-
-
+
+
@@ -1614,8 +1261,8 @@
-
-
+
+
@@ -1669,7 +1316,7 @@
-
+
@@ -1680,10 +1327,10 @@
-
+
-
+
@@ -1693,1279 +1340,54 @@
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -3032,24 +1454,25 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3081,7 +1504,111 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3102,6 +1629,7 @@
+
@@ -3153,7 +1681,7 @@
-
+
@@ -3185,23 +1713,14 @@
-
-
-
-
-
-
-
-
-
@@ -3248,97 +1767,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -3365,6 +1793,8 @@
+
+
@@ -3379,17 +1809,20 @@
+
+
-
+
+
-
+
@@ -3425,143 +1858,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -3610,6 +2006,7 @@
+
@@ -3619,13 +2016,22 @@
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
@@ -3634,7 +2040,4 @@
-
-
-
diff --git a/file_version_info.txt b/file_version_info.txt
index 676acf0..dd149e8 100644
--- a/file_version_info.txt
+++ b/file_version_info.txt
@@ -6,8 +6,8 @@ VSVersionInfo(
ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0.
- filevers=(3, 0, 0, 1),
- prodvers=(3, 0, 0, 1),
+ filevers=(3, 0, 0, 2),
+ prodvers=(3, 0, 0, 2),
# Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f,
# Contains a bitmask that specifies the Boolean attributes of the file.
@@ -31,13 +31,13 @@ VSVersionInfo(
u'040904B0',
[StringStruct(u'CompanyName', u'CreatBot'),
StringStruct(u'FileDescription', u'Hex Installer'),
- StringStruct(u'FileVersion', u'3.0.0.1'),
+ StringStruct(u'FileVersion', u'3.0.0.2'),
StringStruct(u'InternalName', u'Firmware Installer'),
- StringStruct(u'LegalCopyright', u'Copyright(C) CreatBot 2021. All rights reserved'),
+ StringStruct(u'LegalCopyright', u'Copyright(C) CreatBot 2022. All rights reserved'),
StringStruct(u'LegalTrademarks', u'CreatBot'),
StringStruct(u'OriginalFilename', u'Installer.exe'),
StringStruct(u'ProductName', u'Firmware Installer'),
- StringStruct(u'ProductVersion', u'3.0.0.1')])
+ StringStruct(u'ProductVersion', u'3.0.0.2')])
]),
VarFileInfo([VarStruct(u'Translation', [1033, 1200])])
]
diff --git a/requirements.txt b/requirements.txt
index e538cad..b667233 100644
Binary files a/requirements.txt and b/requirements.txt differ
diff --git a/src/avr_isp/__init__.py b/src/avr_isp/__init__.py
index fb9bd4d..4fd08d4 100644
--- a/src/avr_isp/__init__.py
+++ b/src/avr_isp/__init__.py
@@ -2,4 +2,4 @@ from .chipDB import *
from .errorBase import portError
from .intelHex import *
from .ispBase import *
-from .stk500v2 import *
\ No newline at end of file
+from .stk500v2 import *
diff --git a/src/avr_isp/chipDB.py b/src/avr_isp/chipDB.py
index d796fb7..83b0e2d 100644
--- a/src/avr_isp/chipDB.py
+++ b/src/avr_isp/chipDB.py
@@ -4,27 +4,27 @@ Created on 2017年8月15日
@author: CreatBot-SW
'''
-#===============================================================================
+# ===============================================================================
# Database of AVR chips for avr_isp programming. Contains signatures and flash sizes from the AVR datasheets.
# To support more chips add the relevant data to the avrChipDB list.
-#===============================================================================
+# ===============================================================================
avrChipDB = {
- 'ATMega1280': {
- 'signature': [0x1E, 0x97, 0x03],
- 'pageSize': 128,
- 'pageCount': 512,
- },
- 'ATMega2560': {
- 'signature': [0x1E, 0x98, 0x01],
- 'pageSize': 128,
- 'pageCount': 1024,
- },
+ 'ATMega1280': {
+ 'signature': [0x1E, 0x97, 0x03],
+ 'pageSize': 128,
+ 'pageCount': 512,
+ },
+ 'ATMega2560': {
+ 'signature': [0x1E, 0x98, 0x01],
+ 'pageSize': 128,
+ 'pageCount': 1024,
+ },
}
def getChipFromDB(sig):
- for chip in avrChipDB.values():
- if chip['signature'] == sig:
- return chip
- return False
+ for chip in avrChipDB.values():
+ if chip['signature'] == sig:
+ return chip
+ return False
diff --git a/src/avr_isp/intelHex.py b/src/avr_isp/intelHex.py
index 68d57dc..d674168 100644
--- a/src/avr_isp/intelHex.py
+++ b/src/avr_isp/intelHex.py
@@ -5,62 +5,62 @@ Created on 2017年8月15日
'''
import io
-#===============================================================================
+
+# ===============================================================================
# Module to read intel hex files into binary data blobs.
# IntelHex files are commonly used to distribute firmware
# See: http://en.wikipedia.org/wiki/Intel_HEX
-#===============================================================================
+# ===============================================================================
def readHex(filename):
- """
- Read an verify an intel hex file. Return the data as an list of bytes.
- """
- data = []
- extraAddr = 0
- f = io.open(filename, "r")
- for line in f:
- line = line.strip()
- if line[0] != ':':
- raise formatError("Hex file must start with ':' @ " + line)
- recLen = int(line[1:3], 16)
- addr = int(line[3:7], 16) + extraAddr
- recType = int(line[7:9], 16)
- if len(line) != recLen * 2 + 11:
- raise formatError("Length error in hex file @ " + line)
- checkSum = 0
- for i in range(0, recLen + 5):
- checkSum += int(line[i * 2 + 1:i * 2 + 3], 16)
- checkSum &= 0xFF
- if checkSum != 0:
- raise formatError("Checksum error in hex file @ " + line)
+ """
+ Read an verify an intel hex file. Return the data as an list of bytes.
+ """
+ data = []
+ extraAddr = 0
+ f = io.open(filename, "r")
+ for line in f:
+ line = line.strip()
+ if line[0] != ':':
+ raise formatError("Hex file must start with ':' @ " + line)
+ recLen = int(line[1:3], 16)
+ addr = int(line[3:7], 16) + extraAddr
+ recType = int(line[7:9], 16)
+ if len(line) != recLen * 2 + 11:
+ raise formatError("Length error in hex file @ " + line)
+ checkSum = 0
+ for i in range(0, recLen + 5):
+ checkSum += int(line[i * 2 + 1:i * 2 + 3], 16)
+ checkSum &= 0xFF
+ if checkSum != 0:
+ raise formatError("Checksum error in hex file @ " + line)
- if recType == 0: # Data record
- while len(data) < addr + recLen:
- data.append(0)
- for i in range(0, recLen):
- data[addr + i] = int(line[i * 2 + 9:i * 2 + 11], 16)
- elif recType == 1: # End Of File record
- pass
- elif recType == 2: # Extended Segment Address Record
- extraAddr = int(line[9:13], 16) * 16
- elif recType == 3: # Start Segment Address Record
- raise formatError("Dont support record type 03")
- elif recType == 4: # Extended Linear Address Record
- extraAddr = int(line[9:13], 16) << 16
- elif recType == 5: # Start Linear Address Record
- raise formatError("Dont support record type 05")
- else:
- print(recType, recLen, addr, checkSum, line)
- f.close()
- return data
+ if recType == 0: # Data record
+ while len(data) < addr + recLen:
+ data.append(0)
+ for i in range(0, recLen):
+ data[addr + i] = int(line[i * 2 + 9:i * 2 + 11], 16)
+ elif recType == 1: # End Of File record
+ pass
+ elif recType == 2: # Extended Segment Address Record
+ extraAddr = int(line[9:13], 16) * 16
+ elif recType == 3: # Start Segment Address Record
+ raise formatError("Dont support record type 03")
+ elif recType == 4: # Extended Linear Address Record
+ extraAddr = int(line[9:13], 16) << 16
+ elif recType == 5: # Start Linear Address Record
+ raise formatError("Dont support record type 05")
+ else:
+ print(recType, recLen, addr, checkSum, line)
+ f.close()
+ return data
class formatError(Exception):
- def __init__(self, value):
- self.value = value
-
- def __str__(self):
- return repr(self.value)
+ def __init__(self, value):
+ self.value = value
+ def __str__(self):
+ return repr(self.value)
diff --git a/src/avr_isp/ispBase.py b/src/avr_isp/ispBase.py
index 8d94e7f..e5d0f07 100644
--- a/src/avr_isp/ispBase.py
+++ b/src/avr_isp/ispBase.py
@@ -5,74 +5,75 @@ Created on 2017年8月15日
'''
from avr_isp import chipDB
-#===============================================================================
+
+# ===============================================================================
# General interface for Isp based AVR programmers.
# The ISP AVR programmer can load firmware into AVR chips. Which are commonly used on 3D printers.
#
# Needs to be subclassed to support different programmers.
# Currently only the stk500v2 subclass exists.
-#===============================================================================
+# ===============================================================================
class IspBase():
- """
- Base class for ISP based AVR programmers.
- Functions in this class raise an IspError when something goes wrong.
- """
+ """
+ Base class for ISP based AVR programmers.
+ Functions in this class raise an IspError when something goes wrong.
+ """
- def programChip(self, flashData):
- """ Program a chip with the given flash data. """
- self.curExtAddr = -1
- self.chip = chipDB.getChipFromDB(self.getSignature())
- if not self.chip:
- raise IspError("Chip with signature: " + str(self.getSignature()) + "not found")
- self.chipErase()
+ def programChip(self, flashData):
+ """ Program a chip with the given flash data. """
+ self.curExtAddr = -1
+ self.chip = chipDB.getChipFromDB(self.getSignature())
+ if not self.chip:
+ raise IspError("Chip with signature: " + str(self.getSignature()) + "not found")
+ self.chipErase()
- print("Flashing %i bytes" % len(flashData))
- self.writeFlash(flashData)
- print("Verifying %i bytes" % len(flashData))
- self.verifyFlash(flashData)
+ print("Flashing %i bytes" % len(flashData))
+ self.writeFlash(flashData)
+ print("Verifying %i bytes" % len(flashData))
+ self.verifyFlash(flashData)
- def getSignature(self):
- """
- Get the AVR signature from the chip. This is a 3 byte array which describes which chip we are connected to.
- This is important to verify that we are programming the correct type of chip and that we use proper flash block sizes.
- """
- sig = []
- sig.append(self.sendISP([0x30, 0x00, 0x00, 0x00])[3])
- sig.append(self.sendISP([0x30, 0x00, 0x01, 0x00])[3])
- sig.append(self.sendISP([0x30, 0x00, 0x02, 0x00])[3])
- return sig
+ def getSignature(self):
+ """
+ Get the AVR signature from the chip. This is a 3 byte array which describes which chip we are connected to.
+ This is important to verify that we are programming the correct type of chip and that we use proper flash block sizes.
+ """
+ sig = []
+ sig.append(self.sendISP([0x30, 0x00, 0x00, 0x00])[3])
+ sig.append(self.sendISP([0x30, 0x00, 0x01, 0x00])[3])
+ sig.append(self.sendISP([0x30, 0x00, 0x02, 0x00])[3])
+ return sig
- def sendISP(self, data):
- """
- Send data to chip, needs to be implemented in a subclass.
- """
- raise IspError("Called undefined sendISP")
+ def sendISP(self, data):
+ """
+ Send data to chip, needs to be implemented in a subclass.
+ """
+ raise IspError("Called undefined sendISP")
- def chipErase(self):
- """
- Do a full chip erase, clears all data, and lockbits.
- """
- self.sendISP([0xAC, 0x80, 0x00, 0x00])
+ def chipErase(self):
+ """
+ Do a full chip erase, clears all data, and lockbits.
+ """
+ self.sendISP([0xAC, 0x80, 0x00, 0x00])
- def writeFlash(self, flashData):
- """
- Write the flash data, needs to be implemented in a subclass.
- """
- raise IspError("Called undefined writeFlash")
+ def writeFlash(self, flashData):
+ """
+ Write the flash data, needs to be implemented in a subclass.
+ """
+ raise IspError("Called undefined writeFlash")
- def verifyFlash(self, flashData):
- """
- Verify the flash data, needs to be implemented in a subclass.
- """
- raise IspError("Called undefined verifyFlash")
+ def verifyFlash(self, flashData):
+ """
+ Verify the flash data, needs to be implemented in a subclass.
+ """
+ raise IspError("Called undefined verifyFlash")
class IspError(Exception):
- def __init__(self, value):
- self.value = value
+ def __init__(self, value):
+ self.value = value
- def __str__(self):
- return repr(self.value)
+ def __str__(self):
+ return repr(self.value)
diff --git a/src/avr_isp/stk500v2.py b/src/avr_isp/stk500v2.py
index 3435c2d..0281d2e 100644
--- a/src/avr_isp/stk500v2.py
+++ b/src/avr_isp/stk500v2.py
@@ -8,14 +8,14 @@ Created on 2017年8月15日
# The STK500v2 protocol is used by the ArduinoMega2560 and a few other Arduino platforms to load firmware.
# ===============================================================================
-import struct, sys
-import time
+import struct
+import sys
from PyQt5.QtCore import QIODevice, QThread, pyqtSignal
from PyQt5.QtSerialPort import QSerialPort, QSerialPortInfo
from PyQt5.QtWidgets import QApplication
-
from avr_isp import intelHex, ispBase
+
from .errorBase import portError
@@ -88,10 +88,8 @@ class Stk500v2(ispBase.IspBase, QSerialPort):
loadCount = (len(flashData) + pageSize - 1) // pageSize
for i in range(0, loadCount):
- self.sendMessage(
- [0x13, pageSize >> 8, pageSize & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flashData[
- (i * pageSize):(
- i * pageSize + pageSize)])
+ self.sendMessage([0x13, pageSize >> 8, pageSize & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flashData[(i * pageSize):(
+ i * pageSize + pageSize)])
self.progressCallback.emit(i + 1, loadCount * 2)
def verifyFlash(self, flashData):
@@ -191,9 +189,8 @@ class stk500v2Thread(QThread):
self.finished.connect(self.done)
def run(self):
-
+ self.isWork = True
try:
- self.isWork = True
self.programmer = Stk500v2()
if self.callback is not None:
self.programmer.progressCallback.connect(self.callback)
@@ -201,26 +198,24 @@ class stk500v2Thread(QThread):
if self.parent is None:
runProgrammer(self.port, self.speed, self.filename, self.programmer)
else:
- self.stateCallback[str].emit(self.tr("Connecting.."))
+ self.stateCallback[str].emit(self.tr("Connecting..."))
self.msleep(200)
self.programmer.connect(self.port, self.speed)
self.stateCallback[str].emit(self.tr("Programming..."))
self.programmer.programChip(intelHex.readHex(self.filename))
-
except Exception as e:
if self.isInterruptionRequested():
print("Int")
else:
if self.parent is not None:
self.stateCallback[Exception].emit(e)
- # while self.isWork:
- # pass # 等待父进程处理异常
+ while self.isWork:
+ pass # 等待父进程处理异常
else:
raise e
self.isWork = False
finally:
- self.isWork = False
if self.programmer.isConnected():
self.programmer.fastReset()
self.programmer.close()
@@ -266,8 +261,7 @@ def main():
programmer.programChip(intelHex.readHex(sys.argv[2]))
else:
programmer.connect("COM4")
- programmer.programChip(
- intelHex.readHex("D:/OneDrive/Desktop/CreatBot F160 01 EN KTC ( AUTO_LEVELING ).hex"))
+ programmer.programChip(intelHex.readHex("D:/OneDrive/Desktop/CreatBot F160 01 EN KTC ( AUTO_LEVELING ).hex"))
except portError as e:
print(e.value)
print("PortError: " + str(e))
diff --git a/src/firmwareInstaller.py b/src/firmwareInstaller.py
index c4a794a..6f558f2 100644
--- a/src/firmwareInstaller.py
+++ b/src/firmwareInstaller.py
@@ -6,13 +6,12 @@ Created on 2017年8月15日
import os
import sys
-import time
-from PyQt5 import QtSerialPort, QtCore, QtWidgets
+from PyQt5 import QtCore
from PyQt5.Qt import pyqtSignal
from PyQt5.QtCore import QSize, QDir, QTimer
from PyQt5.QtGui import QIcon
-from PyQt5.QtSerialPort import QSerialPortInfo
+from PyQt5.QtSerialPort import QSerialPortInfo, QSerialPort
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QGroupBox, \
QRadioButton, QGridLayout, QWidget, QProgressBar, QStatusBar, QComboBox, QLabel, \
QHBoxLayout, QLineEdit, QPushButton, QFileDialog, QCheckBox
@@ -20,8 +19,6 @@ from PyQt5.QtWidgets import QApplication, QVBoxLayout, QGroupBox, \
from avr_isp.intelHex import formatError
from avr_isp.ispBase import IspError
from avr_isp.stk500v2 import stk500v2Thread, portError
-
-# from DfuseTool import DfuseTool as DFUse
from pydfu import DFUTool as DFUse
if getattr(sys, 'frozen', False):
@@ -64,20 +61,17 @@ class mainWindow(QWidget):
def __init__(self):
super(mainWindow, self).__init__()
- self.setWindowTitle(self.tr("Firmware Installer"))
+ self.setWindowTitle(self.tr("Firmware Installer" + " V3.1.0"))
self.setWindowIcon(QIcon(os.path.join(bundle_dir, "ico.ico")))
self.setFixedSize(QSize(480, 240))
self.setAcceptDrops(True)
self.portUpdateTimer = QTimer()
self.portUpdateTimer.timeout.connect(self.portUpdate)
- self.portUpdateTimer.start(200)
-
+ self.portUpdateTimer.start(100)
self.autoTimer = QTimer()
# self.autoTimer.setSingleShot(True)
- self.autoTimer.timeout.connect(self.portUpdate)
- # self.autoTimer.start(1000)
-
+ self.autoTimer.timeout.connect(self.installFile)
self.task = None
self.initUI()
@@ -135,7 +129,7 @@ class mainWindow(QWidget):
self.autoCheck = QCheckBox(self.tr("Auto Install"))
self.autoTimeLabel = QLabel(self.tr("Idle Time:"))
self.autoTimeLabel2 = QLabel(self.tr("s"))
- self.autoTime = QLineEdit("3")
+ self.autoTime = QLineEdit("2")
self.autoTime.setInputMask("00")
self.autoTime.setMaximumWidth(20)
@@ -174,8 +168,7 @@ class mainWindow(QWidget):
# 计数栏
self.countBar = QStatusBar()
self.countBar.setSizeGripEnabled(False)
- self.countBar.setStyleSheet(
- "QStatusBar::item { border: 0 } QLabel {border:0; font-size: 14px; font-weight: bold}")
+ self.countBar.setStyleSheet("QStatusBar::item { border: 0 } QLabel {border:0; font-size: 14px; font-weight: bold}")
countSuccessLabel = QLabel("Success: ")
countFailureLabel = QLabel("Failure: ")
self.countSuccess = countLabel("0")
@@ -231,9 +224,9 @@ class mainWindow(QWidget):
self.statusBar.messageChanged.connect(self.stateClearAction)
# 默认选中
+ self.autoCheck.click()
+ self.autoCheck.click()
self.autoRadio.click()
- # self.manualRadio.click()
- # self.autoCheck.click()
self.fileBtn.clicked.connect(self.selectFile)
self.installBtn.clicked.connect(self.installFile)
@@ -244,36 +237,24 @@ class mainWindow(QWidget):
def portUpdate(self, forceUpdate=False):
""" Auto 监听端口 """
- print("search port")
if self.autoRadio.isChecked():
-
self.baudCombo.setCurrentText("115200")
# self.portCombo.addItems(portList())
- # self.portCombo.clear()
- port_list = QSerialPortInfo.availablePorts()
- for port in port_list:
- print(':--:', port.portName(), port.description())
- if port.description() not in ["Arduino Mega 2560", "USB-SERIAL CH340"]: # 过滤2560和CH340
+ self.portCombo.clear()
+ for port in QSerialPortInfo.availablePorts():
+ if port.description() not in ["Arduino Mega 2560", "USB-SERIAL CH340", "USB 串行设备"]: # 过滤2560和CH340
continue
- self.portCombo.addItem(port.portName() + " (" + port.description() + ")", port.portName())
-
- if len(port_list) > 0:
- port = port_list[0]
- info = QSerialPortInfo(port)
- print(info.productIdentifier())
- if info.productIdentifier() == 0:
- return
- if not self.installBtn.isEnabled():
- self.installFile()
-
+ portInfo = QSerialPortInfo(port)
+ self.portCombo.addItem(port.portName() + " (" + port.description() + ")", (port.portName(), portInfo.vendorIdentifier()))
else:
- currentPortData = self.portCombo.currentData()
- if forceUpdate or (currentPortData and currentPortData not in [port.portName() for port in
- QSerialPortInfo.availablePorts()]):
+ currentPortData = self.portCombo.currentText()
+ if forceUpdate or (currentPortData and currentPortData not in [port.portName() for port in QSerialPortInfo.availablePorts()]):
self.portCombo.clear()
for port in QSerialPortInfo.availablePorts():
- self.portCombo.addItem(port.portName() + " (" + port.description() + ")", port.portName())
- self.portCombo.setCurrentIndex(self.portCombo.findData(currentPortData))
+ portInfo = QSerialPortInfo(port)
+ self.portCombo.addItem(port.portName() + " (" + port.description() + ")",
+ (port.portName(), portInfo.vendorIdentifier()))
+ self.portCombo.setCurrentIndex(self.portCombo.findText(currentPortData))
self.portCombo.setSizeAdjustPolicy(QComboBox.AdjustToContents)
self.baudCombo.setSizeAdjustPolicy(QComboBox.AdjustToContents)
@@ -285,14 +266,6 @@ class mainWindow(QWidget):
if not check and self.autoTimer.remainingTime() > 0:
self.stopInstall()
- if check:
- # 开启自动安装的端口扫描
- self.portUpdateTimer.stop()
- self.autoTimer.start(int(self.autoTime.text())*1000)
- else:
- self.autoTimer.stop()
- self.portUpdateTimer.start(200)
-
def autoTimeChangeAction(self):
""" 修改时间间隔 """
self.autoTime.clearFocus()
@@ -329,65 +302,35 @@ class mainWindow(QWidget):
self.file.setText(hexFileDialog.selectedFiles()[0])
def installFile(self, notFromButton=True):
- """ 开始安装 """
- print("-------------------开始安装-------------------")
- # for port in QSerialPortInfo.availablePorts():
- # print('port.description===', port.portName())
- # print('port.description===', port.description())
- # info = QSerialPortInfo(port)
- # print(info.productIdentifier())
- # print(info.vendorIdentifier())
+ if self.portCombo.currentData() is None:
+ return
if self.file.text() == "":
if not notFromButton:
self.selectFile()
self.installFile(True)
else:
- if self.autoTimer.remainingTime() > 0:
+ if self.autoTimer.remainingTime() != -1:
self.autoTimer.stop()
- port_list = QSerialPortInfo.availablePorts()
- if len(port_list) <= 0:
- QtWidgets.QMessageBox.about(self, "提示", "没有可用的串口!")
- return
+ self.portBox.setDisabled(True)
+ self.fileBox.setDisabled(True)
+ self.installBtn.setDisabled(True)
- port = port_list[0]
- info = QSerialPortInfo(port)
+ self.progress.show()
+ self.resize()
- port_Name = None
- baud_rate = None
- if self.manualRadio.isChecked():
- if self.portCombo.currentData() is None:
- QtWidgets.QMessageBox.about(self, "提示", "请选择串口设备")
- return
- else:
- port_Name = self.portCombo.currentData()
- baud_rate = int(self.baudCombo.currentText())
-
- else:
- port_Name = info.portName()
- baud_rate = QtSerialPort.QSerialPort.Baud115200
-
- print("port:", port_Name)
- print("baudCombo:", baud_rate)
- print(info.portName())
- print(info.description())
- print(info.productIdentifier())
- print(info.vendorIdentifier())
- if info.productIdentifier() == 0:
- self.autoTimer.start(1000)
- pass
-
- if info.vendorIdentifier() == 1155:
- print("------命令开启DFU模式 start------")
+ info = self.portCombo.currentData()
+ if info[1] == 1155:
+ self.stopBtn.setEnabled(False)
self.statusBar.showMessage("Serial to DFU...")
- serial = QtSerialPort.QSerialPort(self)
- serial.setPortName(port_Name)
- serial.setBaudRate(baud_rate)
- serial.setDataBits(QtSerialPort.QSerialPort.Data8)
- serial.setParity(QtSerialPort.QSerialPort.NoParity)
- serial.setStopBits(QtSerialPort.QSerialPort.OneStop)
- serial.setFlowControl(QtSerialPort.QSerialPort.NoFlowControl)
+ serial = QSerialPort(self)
+ serial.setPortName(info[0])
+ serial.setBaudRate(QSerialPort.Baud115200)
+ serial.setDataBits(QSerialPort.Data8)
+ serial.setParity(QSerialPort.NoParity)
+ serial.setStopBits(QSerialPort.OneStop)
+ serial.setFlowControl(QSerialPort.NoFlowControl)
if not serial.open(QtCore.QIODevice.ReadWrite):
# QtWidgets.QMessageBox.about(self, "提示", "无法打开串口!")
@@ -396,25 +339,35 @@ class mainWindow(QWidget):
data = bytes("M9999\r", encoding='utf-8')
data = QtCore.QByteArray(data)
serial.write(data)
- print("------命令开启DFU模式 end------")
+
self.statusBar.showMessage("Serial to dfu...")
- self.task = DFUse(self, self.file.text(), self.progressUpdate)
+ self.task = DFUse(self, self.portCombo.currentData()[0], int(self.baudCombo.currentText()), self.file.text(),
+ self.progressUpdate)
self.task.stateCallback[str].connect(self.stateUpdate)
self.task.stateCallback[Exception].connect(self.stateUpdate)
self.task.finished.connect(self.autoAction) # 检查是否自动烧写,并启动。
# self.task.start()
- elif info.vendorIdentifier() != 0:
- self.task = stk500v2Thread(self, self.portCombo.currentData(), int(self.baudCombo.currentText()),
+ elif info[1] != 0:
+ self.stopBtn.setEnabled(True)
+ self.task = stk500v2Thread(self, info[0], int(self.baudCombo.currentText()),
self.file.text(), self.progressUpdate)
self.task.stateCallback[str].connect(self.stateUpdate)
self.task.stateCallback[Exception].connect(self.stateUpdate)
self.task.finished.connect(self.autoAction)
self.task.start()
- # 开始烧录,刷新UI
- # self.statusBar.showMessage(" ")
+ return
+
+ if self.file.text() == "":
+ if not notFromButton:
+ self.selectFile()
+ self.installFile(True)
+ else:
+ if self.autoTimer.remainingTime() != -1:
+ self.autoTimer.stop()
+
self.portBox.setDisabled(True)
self.fileBox.setDisabled(True)
self.installBtn.setDisabled(True)
@@ -422,6 +375,14 @@ class mainWindow(QWidget):
self.progress.show()
self.resize()
+ self.task = DFUse(self, self.portCombo.currentData()[0], int(self.baudCombo.currentText()), self.file.text(),
+ self.progressUpdate)
+ self.task.stateCallback[str].connect(self.stateUpdate)
+ self.task.stateCallback[Exception].connect(self.stateUpdate)
+ self.task.finished.connect(self.autoAction)
+ self.task.start()
+ self.statusBar.showMessage(" ")
+
def stopInstall(self, succeed=False, autoInstall=False):
""" 停止自动安装 """
if autoInstall:
@@ -440,8 +401,8 @@ class mainWindow(QWidget):
self.countSuccess.setText(str(int(self.countSuccess.text()) + 1))
self.task = None
else:
- # if self.autoTimer.remainingTime() != -1:
- # self.autoTimer.stop()
+ if self.autoTimer.remainingTime() != -1:
+ self.autoTimer.stop()
if self.task is not None and self.task.isRunning():
self.task.finished.disconnect()
if self.task.isReady():
@@ -459,14 +420,10 @@ class mainWindow(QWidget):
def autoAction(self):
""" 上一个任务结束后,开启新的烧录任务 """
- self.task = None
- self.statusBar.showMessage("Done!")
+ self.stopBtn.setEnabled(True)
self.stopInstall(True, self.autoCheck.isChecked())
-
# 开启自动安装
if self.autoCheck.isChecked():
- if self.autoTimer.remainingTime() > 0:
- self.autoTimer.stop()
self.autoTimer.start(int(self.autoTime.text()) * 1000)
def resize(self):
@@ -481,31 +438,24 @@ class mainWindow(QWidget):
""" 安装状态 """
self.tryAgainLabel.setHidden(True)
self.tryAgain.setHidden(True)
- if self.task.isReady():
- self.tryAgain.setText("0")
+ # if self.task.isReady():
+ # self.tryAgain.setText("0")
- print(stateOrError, str)
if type(stateOrError) == str:
- print("222---")
# self.statusBar.setStyleSheet("QStatusBar::item { border: 0 } QLabel {color: red; font-weight: bold}")
self.statusBar.setStyleSheet(
"QStatusBar {font-weight: bold; color: black} QStatusBar::item { border: 0 } QLabel {font-weight: bold}")
if self.task is not None and not self.task.isWork and not self.autoCheck.isChecked():
- print("statusBar---")
self.statusBar.showMessage(stateOrError, 3000)
else:
- print("else---")
self.statusBar.showMessage(stateOrError)
-
else:
- print("333---")
self.task.requestInterruption()
self.statusBar.setStyleSheet(
"QStatusBar {font-weight: bold; color: red} QStatusBar::item { border: 0 } QLabel {font-weight: bold; color: red}")
if type(stateOrError) == portError:
- if (stateOrError.value in [portError.errorInvalid, portError.errorBusy]) and (
- int(self.tryAgain.text()) < 20):
+ if (stateOrError.value in [portError.errorInvalid, portError.errorBusy]) and (int(self.tryAgain.text()) < 20):
self.statusBar.showMessage("PortError: " + str(stateOrError))
self.tryAgain.setText(str(int(self.tryAgain.text()) + 1))
self.tryAgainLabel.setVisible(True)
@@ -531,7 +481,6 @@ class mainWindow(QWidget):
else:
self.statusBar.showMessage("Error: " + str(stateOrError), 5000)
self.stopInstall()
- print("1111---")
self.task.isWork = False
self.task.wait(100)
@@ -539,7 +488,6 @@ class mainWindow(QWidget):
if __name__ == '__main__':
-
app = QApplication(sys.argv)
win = mainWindow()
diff --git a/src/pydfu.py b/src/pydfu.py
index 98f0b81..c305e0b 100644
--- a/src/pydfu.py
+++ b/src/pydfu.py
@@ -18,10 +18,12 @@ import collections
import inspect
import re
import struct
-import sys, time
+import sys
+import time
+import zlib
+
import usb.core
import usb.util
-import zlib
# USB request __TIMEOUT
__TIMEOUT = 4000
@@ -658,24 +660,213 @@ def main():
# if __name__ == "__main__":
# main()
-from avr_isp.errorBase import portError
-
-from PyQt5.QtCore import QIODevice, QThread, pyqtSignal
+from PyQt5.QtCore import QIODevice, QThread, pyqtSignal, QByteArray
from PyQt5.QtSerialPort import QSerialPort, QSerialPortInfo
from PyQt5.QtWidgets import QApplication
+from avr_isp import ispBase
+from avr_isp.errorBase import portError
+
+
+class STM32Dev(ispBase.IspBase, QSerialPort):
+ progressCallback = pyqtSignal(int, int)
+
+ def __init__(self):
+ super(STM32Dev, self).__init__()
+ self.seq = 1
+ self.lastAddr = -1
+ self.portInfo = None
+
+ def connect(self, port='COM4', speed=115200):
+ print("connect", port)
+ self.portInfo = QSerialPortInfo(port)
+ print("portInfo", self.portInfo)
+ self.setPortName(port)
+ # self.setBaudRate(speed)
+ # self.setPortName("COM3")
+ self.setBaudRate(QSerialPort.Baud115200)
+ self.setDataBits(QSerialPort.Data8)
+ self.setParity(QSerialPort.NoParity)
+ self.setStopBits(QSerialPort.OneStop)
+ self.setFlowControl(QSerialPort.NoFlowControl)
+
+ if self.portInfo.isNull():
+ raise portError(portError.errorInvalid, port)
+ else:
+ if self.portInfo.isBusy():
+ raise portError(portError.errorBusy, port)
+ else:
+ if self.open(QIODevice.ReadWrite):
+ # self.setBreakEnabled()
+ print("open")
+ # self.entryISP()
+ print("open--end")
+ else:
+ raise portError(portError.errorOpen, port)
+
+ def close(self):
+ super(STM32Dev, self).close()
+ self.portInfo = None
+
+ def serial_DFU(self):
+ print("serial_DFU")
+ # if not self.open(QIODevice.ReadWrite):
+ # # QtWidgets.QMessageBox.about(self, "提示", "无法打开串口!")
+ # return
+ print("1111")
+ data = bytes("M9999\r", encoding='utf-8')
+ data = QByteArray(data)
+ print("2222")
+ # self.write(data)
+ print(self.write(data))
+ print("serial_DFU---end")
+ self.close()
+
+ def entryISP(self):
+ self.seq = 1
+ # Reset the controller
+ self.setDataTerminalReady(True)
+ QThread.msleep(100)
+ self.setDataTerminalReady(False)
+ QThread.msleep(200)
+ self.clear()
+ print("=====")
+
+ recv = self.sendMessage([1])[3:]
+ if "".join([chr(c) for c in recv]) != "AVRISP_2":
+ raise ispBase.IspError("Unkonwn bootloaders!")
+
+ if self.sendMessage([0x10, 0xc8, 0x64, 0x19, 0x20, 0x00, 0x53, 0x03, 0xac, 0x53, 0x00, 0x00]) != [0x10, 0x00]:
+ raise ispBase.IspError("Failed to enter programming mode!")
+
+ def leaveISP(self):
+ if self.portInfo is not None:
+ if self.sendMessage([0x11]) != [0x11, 0x00]:
+ raise ispBase.IspError("Failed to leave programming mode!")
+
+ def isConnected(self):
+ return self.isOpen()
+
+ def sendISP(self, data):
+ recv = self.sendMessage([0x1D, 4, 4, 0, data[0], data[1], data[2], data[3]])
+ return recv[2:6]
+
+ def writeFlash(self, flashData):
+ # Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
+ pageSize = self.chip['pageSize'] * 2
+ flashSize = pageSize * self.chip['pageCount']
+ if flashSize > 0xFFFF:
+ self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
+ else:
+ self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
+
+ loadCount = (len(flashData) + pageSize - 1) // pageSize
+ for i in range(0, loadCount):
+ self.sendMessage([0x13, pageSize >> 8, pageSize & 0xFF, 0xc1, 0x0a, 0x40, 0x4c, 0x20, 0x00, 0x00] + flashData[(i * pageSize):(
+ i * pageSize + pageSize)])
+ self.progressCallback.emit(i + 1, loadCount * 2)
+
+ def verifyFlash(self, flashData):
+ # Set load addr to 0, in case we have more then 64k flash we need to enable the address extension
+ flashSize = self.chip['pageSize'] * 2 * self.chip['pageCount']
+ if flashSize > 0xFFFF:
+ self.sendMessage([0x06, 0x80, 0x00, 0x00, 0x00])
+ else:
+ self.sendMessage([0x06, 0x00, 0x00, 0x00, 0x00])
+
+ loadCount = (len(flashData) + 0xFF) // 0x100
+ for i in range(0, loadCount):
+ recv = self.sendMessage([0x14, 0x01, 0x00, 0x20])[2:0x102]
+ self.progressCallback.emit(loadCount + i + 1, loadCount * 2)
+ for j in range(0, 0x100):
+ if i * 0x100 + j < len(flashData) and flashData[i * 0x100 + j] != recv[j]:
+ raise ispBase.IspError('Verify error at: 0x%x' % (i * 0x100 + j))
+
+ def fastReset(self):
+ QThread.msleep(50)
+ self.setDataTerminalReady(True)
+ self.setDataTerminalReady(False)
+
+ def sendMessage(self, data):
+ message = struct.pack(">BBHB", 0x1B, self.seq, len(data), 0x0E)
+ for c in data:
+ message += struct.pack(">B", c)
+ checksum = 0
+ for c in message:
+ checksum ^= c
+ message += struct.pack(">B", checksum)
+ try:
+ print("----00")
+ self.write(message)
+ self.flush()
+ print("----11")
+ except:
+ raise ispBase.IspError("Serial send timeout")
+ self.seq = (self.seq + 1) & 0xFF
+ print("----222")
+ # time.sleep(1)
+ if self.waitForReadyRead(1000):
+ print("----33")
+ return self.recvMessage()
+ else:
+ print("----44")
+ raise ispBase.IspError("Serial recv timeout")
+
+ def recvMessage(self):
+ state = 'Start'
+ checksum = 0
+ while True:
+ s = self.read(1)
+ if len(s) < 1:
+ if self.waitForReadyRead(20):
+ continue
+ else:
+ raise ispBase.IspError("Serial read timeout")
+ b = struct.unpack(">B", s)[0]
+ checksum ^= b
+ if state == 'Start':
+ if b == 0x1B:
+ state = 'GetSeq'
+ checksum = 0x1B
+ elif state == 'GetSeq':
+ state = 'MsgSize1'
+ elif state == 'MsgSize1':
+ msgSize = b << 8
+ state = 'MsgSize2'
+ elif state == 'MsgSize2':
+ msgSize |= b
+ state = 'Token'
+ elif state == 'Token':
+ if b != 0x0E:
+ state = 'Start'
+ else:
+ state = 'Data'
+ data = []
+ elif state == 'Data':
+ data.append(b)
+ if len(data) == msgSize:
+ state = 'Checksum'
+ elif state == 'Checksum':
+ if checksum != 0:
+ state = 'Start'
+ else:
+ return data
+
class DFUTool(QThread):
print("DFUTool(QThread)")
stateCallback = pyqtSignal([str], [Exception])
+
progressCallback = pyqtSignal(int, int)
- def __init__(self, parent, filename, callback=None):
+ def __init__(self, parent, port, speed, filename, callback=None):
super(DFUTool, self).__init__()
- print("----------------------")
self.parent = parent
+ self.port = port
+ self.speed = speed
self.filename = filename
- self.progress = callback
+ self.callback = callback
+ self.programmer = None
self.isWork = False
self.finished.connect(self.done)
@@ -721,6 +912,7 @@ class DFUTool(QThread):
def w(state):
if state is False:
+ self.stateCallback[Exception].emit(portError(portError.errorOpen, port))
self.stateCallback[str].emit("Done!")
self.quit()
return
@@ -737,30 +929,40 @@ class DFUTool(QThread):
self.thread = DFUSearch(self, kwargs=kwargs)
self.thread.searchResults.connect(w) # 异步完成后执行函数w
self.thread.start()
+ self.isWork = True
def cl_progress(self, addr, offset, size):
"""Prints a progress report suitable for use on the command line."""
+ print("offset", offset, "size", size)
self.progressCallback.emit(offset, size)
+ def disconnect(self, QMetaObject_Connection=None):
+ print("QMetaObject_Connection")
+
def run(self):
- if self.progress is not None:
- self.progressCallback.connect(self.progress)
- print(self.args)
- self.stateCallback[str].emit("read fils")
- with open(self.args.path, "rb") as fin:
- dfu_file = fin.read()
-
- if dfu_file is None:
- print("file is None")
- return
-
self.isWork = True
-
- elem = {"addr": 134217728, "size": len(dfu_file), "data": dfu_file}
-
try:
- self.stateCallback[str].emit("Write file...")
- write_elements([elem], self.args.mass_erase, progress=self.cl_progress)
+ with open(self.args.path, "rb") as fin:
+ dfu_file = fin.read()
+
+ if dfu_file is None:
+ print("file is None")
+ return
+ elem = {"addr": 134217728, "size": len(dfu_file), "data": dfu_file}
+
+ self.programmer = STM32Dev()
+
+ if self.callback is not None:
+ self.progressCallback.connect(self.callback)
+
+ if self.parent is None:
+ pass
+
+ else:
+ self.stateCallback[str].emit(self.tr("Programming..."))
+ # self.programmer.
+ write_elements([elem], self.args.mass_erase, progress=self.cl_progress)
+ exit_dfu() # 退出DFU模式
except Exception as err:
if self.isInterruptionRequested():
print("int")
@@ -773,16 +975,13 @@ class DFUTool(QThread):
raise err
self.isWork = False
finally:
- self.isWork = False
- self.stateCallback[str].emit("Exiting DFU...")
- print("Exiting DFU...")
- exit_dfu()
- # 退出DFU模式
- print("Done...")
- self.ude = None
+ self.stateCallback[str].emit("Done!")
+ self.programmer = None
def isReady(self):
return True
+ return self.programmer is not None and self.programmer.isConnected()
+
try:
status = get_status()
print(status)
@@ -807,6 +1006,9 @@ class DFUTool(QThread):
print("Failure!")
def terminate(self):
+ if self.thread.isRunning():
+ self.thread.exit()
+
self.requestInterruption()
return super(DFUTool, self).terminate()
@@ -830,11 +1032,11 @@ class DFUSearch(QThread):
devices = get_dfu_devices(**self.kwargs)
attempts += 1
print("搜索DFU设备", attempts)
- if attempts > 10:
+ if attempts > 20:
self.searchResults.emit(False)
self.quit()
return
- time.sleep(2)
+ time.sleep(1)
self.searchResults.emit(True)