Skip to content

Commit c390632

Browse files
committed
update:重构V0.0.2,
支持bin格式自定义下载地址 支持是否擦除芯片
1 parent 38270ab commit c390632

File tree

1 file changed

+296
-41
lines changed

1 file changed

+296
-41
lines changed

MCUProg.py

Lines changed: 296 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,288 @@
11
import sys,os
2-
from PySide6.QtWidgets import QFileDialog, QApplication, QMainWindow
2+
3+
from PySide6 import __version__ as PySide6_version
4+
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
5+
QMetaObject, QObject, QPoint, QRect,
6+
QSize, QTime, QUrl, Qt,QThread,Signal,Slot)
7+
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
8+
QFont, QFontDatabase, QGradient, QIcon,
9+
QImage, QKeySequence, QLinearGradient, QPainter,
10+
QPalette, QPixmap, QRadialGradient, QTransform)
11+
from PySide6.QtWidgets import (QApplication,QCheckBox,QFileDialog,QFontDialog,
12+
QComboBox, QLabel, QLineEdit,QMainWindow, QProgressBar, QPushButton,
13+
QSizePolicy,QStatusBar, QWidget,QDialog)
14+
315
from pyocd.core.helpers import ConnectHelper
416
from pyocd.core.target import Target
517
from pyocd.core.memory_map import MemoryType
618
from pyocd.coresight.cortex_m import CortexM
719
from pyocd.flash.file_programmer import FileProgrammer
820
from pyocd.tools.lists import ListGenerator
9-
from MCUProg_ui import Ui_MainWindow
21+
from pyocd._version import version as pyocd_version
22+
23+
version = "0.0.2"
24+
25+
if getattr(sys, 'frozen', False):
26+
run_dir = sys._MEIPASS
27+
exe_dir = os.path.dirname(os.path.realpath(sys.executable))
28+
else:
29+
run_dir = os.path.dirname(os.path.abspath(__file__))
30+
exe_dir = run_dir
31+
32+
icon_path = os.path.join(run_dir,"icons","tool_icon.ico")
33+
ui_font_path = os.path.join(run_dir,"resources","OPPOSans-regular.ttf")
34+
35+
mcuprog_tool_info = '''这是一个MCU烧录工具
36+
37+
版本: V{0}
38+
作者: 打盹的消防车
39+
作者仓库:
40+
https://github.com/Dozingfiretruck
41+
https://gitee.com/Dozingfiretruck
42+
43+
感谢:
44+
PySide6: V{1}
45+
pyocd: V{2}
46+
UI字体: OPPOSans
47+
'''.format(version,PySide6_version,pyocd_version)
48+
49+
class QComboBox2(QComboBox):
50+
pop_up = Signal()
51+
def showPopup(self):
52+
self.pop_up.emit()
53+
super(QComboBox2, self).showPopup()
54+
55+
class Thread2(QThread):
56+
finish = Signal(str)
57+
def __init__(self, func, *args):
58+
super().__init__()
59+
self.func = func
60+
self.args = args
61+
def run(self):
62+
res = self.func(*self.args)
63+
# 任务完成后发出信号
64+
self.finish.emit(res)
1065

66+
def programmer(MainWindow):
67+
board = MainWindow.session.board
68+
target = board.target
69+
70+
if not MainWindow.file_path.endswith('.bin'):
71+
base_address = None
72+
else:
73+
if MainWindow.base_address_lineEdit.text() == '':
74+
base_address = None
75+
else:
76+
base_address = int(MainWindow.base_address_lineEdit.text(), base=0)
77+
78+
if MainWindow.chip_erase_checkBox.isChecked():
79+
chip_erase = "chip"
80+
else:
81+
chip_erase = "auto"
82+
83+
# Load firmware into device.
84+
FileProgrammer(MainWindow.session,
85+
chip_erase=chip_erase,
86+
smart_flash=False,
87+
trust_crc=False,
88+
keep_unwritten=True,
89+
no_reset=True,
90+
progress = MainWindow.progress
91+
).program(MainWindow.file_path,
92+
base_address=base_address)
93+
# Reset
94+
target.reset_and_halt()
95+
1196
class MainWindow(QMainWindow):
97+
app_w = 480
98+
app_h = 280
1299
file_path = ''
13100
allProbes = None
14101
Probe = None
15102
session = None
16103
frequency = {'10MHZ':10000000,'5MHZ':5000000,'2MHZ':2000000,'1MHZ':1000000,'500kHZ':500000,'200kHZ':200000,'100kHZ':100000,'50kHZ':50000,'20kHZ':20000,'10kHZ':10000,'5kHZ':5000}
17104
def __init__(self, parent = None) :
18105
super().__init__(parent)
19-
self.ui = Ui_MainWindow()
20-
self.ui.setupUi(self)
21-
self.ui.file_selection_button.clicked.connect(self.file_selection_button_click)
22-
self.ui.usb_connect_button.clicked.connect(self.usb_connect_button_click)
23-
self.ui.flash_button.clicked.connect(self.flash_button_click)
24-
self.ui.usb_comboBox.pop_up.connect(self.usb_selection)
25-
self.ui.speed_comboBox.addItems(['10MHZ','5MHZ','2MHZ','1MHZ','500kHZ','200kHZ','100kHZ','50kHZ','20kHZ','10kHZ','5kHZ'])
106+
if not self.objectName():
107+
self.setObjectName(u"MCUProg")
108+
self.setWindowTitle("MCUProg V"+version)
109+
self.resize(self.app_w, self.app_h)
110+
self.setMinimumSize(QSize(self.app_w, self.app_h))
111+
self.setMaximumSize(QSize(self.app_w, self.app_h))
112+
# 图标
113+
icon = QIcon(icon_path)
114+
self.setWindowIcon(icon)
115+
# 字体
116+
QFontDatabase.addApplicationFont(ui_font_path)
117+
# QFontDatabase.applicationFontFamilies(id)
118+
ui_font = QFont("HarmonyOS Sans",10,QFont.Medium)
119+
self.setFont(ui_font)
120+
121+
self.centralwidget = QWidget(self)
122+
self.centralwidget.setObjectName(u"centralwidget")
123+
124+
# 菜单栏
125+
self.menubar = self.menuBar()
126+
self.menubar.setObjectName(u"menubar")
127+
self.setMenuBar(self.menubar)
128+
self.statusbar = QStatusBar(self)
129+
self.statusbar.setObjectName(u"statusbar")
130+
self.setStatusBar(self.statusbar)
131+
132+
# 菜单栏 - 菜单
133+
self.menu_file = self.menubar.addMenu(QCoreApplication.translate("MCUProg", "菜单", None))
134+
# # 菜单 - 安装pack
135+
# self.install_pack = self.menu_file.addAction(QCoreApplication.translate("MCUProg", "安装pack", None))
136+
# self.install_pack.triggered.connect(self.click_install_pack)
137+
# 菜单 - 退出
138+
self.action_file_exit = self.menu_file.addAction(QCoreApplication.translate("MCUProg", "退出", None))
139+
self.action_file_exit.triggered.connect(self.click_exit)
140+
# 帮助
141+
self.menu_file = self.menubar.addMenu(QCoreApplication.translate("MCUProg", "帮助", None))
142+
# 帮助 -关于
143+
self.action_file_exit = self.menu_file.addAction(QCoreApplication.translate("MCUProg", "关于", None))
144+
self.action_file_exit.triggered.connect(self.click_about)
145+
146+
# 目标芯片标签
147+
self.target_label = QLabel(self.centralwidget)
148+
self.target_label.setObjectName(u"target_label")
149+
self.target_label.setGeometry(QRect(20, 20, 50, 20))
150+
# 目标芯片选择
151+
self.targets_comboBox = QComboBox2(self.centralwidget)
152+
self.targets_comboBox.setObjectName(u"targets_comboBox")
153+
self.targets_comboBox.setGeometry(QRect(80, 20, 160, 20))
154+
# 烧录速度标签
155+
self.speed_label = QLabel(self.centralwidget)
156+
self.speed_label.setObjectName(u"speed_label")
157+
self.speed_label.setGeometry(QRect(260, 20, 50, 20))
158+
# 烧录速度选择
159+
self.speed_comboBox = QComboBox(self.centralwidget)
160+
self.speed_comboBox.setObjectName(u"speed_comboBox")
161+
self.speed_comboBox.setGeometry(QRect(320, 20, 120, 20))
162+
self.speed_comboBox.addItems(['10MHZ','5MHZ','2MHZ','1MHZ','500kHZ','200kHZ','100kHZ','50kHZ','20kHZ','10kHZ','5kHZ'])
163+
# 烧录器标签
164+
self.downloard_label = QLabel(self.centralwidget)
165+
self.downloard_label.setObjectName(u"downloard_label")
166+
self.downloard_label.setGeometry(QRect(20, 60, 53, 20))
167+
# 烧录器选择
168+
self.usb_comboBox = QComboBox2(self.centralwidget)
169+
self.usb_comboBox.setObjectName(u"usb_comboBox")
170+
self.usb_comboBox.setGeometry(QRect(80, 60, 260, 23))
171+
# 连接按钮
172+
self.usb_connect_button = QPushButton(self.centralwidget)
173+
self.usb_connect_button.setObjectName(u"usb_connect_button")
174+
self.usb_connect_button.setGeometry(QRect(360, 60, 80, 20))
175+
# 烧录固件标签
176+
self.file_label = QLabel(self.centralwidget)
177+
self.file_label.setObjectName(u"file_label")
178+
self.file_label.setGeometry(QRect(20, 100, 53, 20))
179+
# 烧录固件
180+
self.file_lineEdit = QLineEdit(self.centralwidget)
181+
self.file_lineEdit.setObjectName(u"file_lineEdit")
182+
self.file_lineEdit.setGeometry(QRect(80, 100, 260, 20))
183+
# 烧录固件选择
184+
self.file_selection_button = QPushButton(self.centralwidget)
185+
self.file_selection_button.setObjectName(u"file_selection_button")
186+
self.file_selection_button.setGeometry(QRect(360, 100, 80, 20))
187+
# 烧录地址标签
188+
self.base_address_label = QLabel(self.centralwidget)
189+
self.base_address_label.setObjectName(u"base_address_label")
190+
self.base_address_label.setGeometry(QRect(20, 140, 140, 20))
191+
# 烧录地址
192+
self.base_address_lineEdit = QLineEdit(self.centralwidget)
193+
self.base_address_lineEdit.setObjectName(u"base_address_lineEdit")
194+
self.base_address_lineEdit.setGeometry(QRect(160, 140, 180, 20))
195+
# 是否擦除芯片
196+
self.chip_erase_checkBox = QCheckBox(self.centralwidget)
197+
self.chip_erase_checkBox.setObjectName(u"chip_erase_checkBox")
198+
self.chip_erase_checkBox.setGeometry(QRect(340, 140, 100, 20))
199+
# 进度条
200+
self.flash_progressBar = QProgressBar(self.centralwidget)
201+
self.flash_progressBar.setObjectName(u"flash_progressBar")
202+
self.flash_progressBar.setGeometry(QRect(20, 180, 320, 20))
203+
self.flash_progressBar.setValue(0)
204+
# 烧录按钮
205+
self.flash_button = QPushButton(self.centralwidget)
206+
self.flash_button.setObjectName(u"flash_button")
207+
self.flash_button.setGeometry(QRect(360, 180, 80, 20))
208+
# 信息标签
209+
self.logs_label = QLabel(self.centralwidget)
210+
self.logs_label.setObjectName(u"logs_label")
211+
self.logs_label.setGeometry(QRect(20, 220, 420, 20))
212+
213+
# 信号与槽
214+
self.usb_comboBox.pop_up.connect(self.usb_selection)
215+
self.usb_connect_button.clicked.connect(self.usb_connect_button_click)
216+
self.targets_comboBox.pop_up.connect(self.target_selection)
217+
self.file_selection_button.clicked.connect(self.file_selection_button_click)
218+
self.flash_button.clicked.connect(self.flash_button_click)
219+
220+
self.setCentralWidget(self.centralwidget)
221+
222+
self.retranslateUi()
223+
224+
QMetaObject.connectSlotsByName(self)
225+
226+
self.usb_selection()
227+
self.target_selection()
228+
229+
def retranslateUi(self):
230+
self.file_selection_button.setText(QCoreApplication.translate("MCUProg", u"选择固件", None))
231+
self.flash_button.setText(QCoreApplication.translate("MCUProg", u"烧录", None))
232+
self.usb_connect_button.setText(QCoreApplication.translate("MCUProg", u"连接", None))
233+
self.target_label.setText(QCoreApplication.translate("MCUProg", u"目标芯片", None))
234+
self.downloard_label.setText(QCoreApplication.translate("MCUProg", u"烧录器", None))
235+
self.file_label.setText(QCoreApplication.translate("MCUProg", u"烧录固件", None))
236+
self.speed_label.setText(QCoreApplication.translate("MCUProg", u"烧录速度", None))
237+
self.base_address_label.setText(QCoreApplication.translate("MCUProg", u"烧录地址 (bin格式生效)", None))
238+
# self.base_address_lineEdit.setText(QCoreApplication.translate("MCUProg", u"0x08000000", None))
239+
self.chip_erase_checkBox.setText(QCoreApplication.translate("MCUProg", u"是否擦除芯片", None))
240+
241+
242+
def usb_selection(self):
26243
self.usb_probe()
244+
245+
def target_selection(self):
246+
self.targets_comboBox.clear()
27247
list_targets = ListGenerator.list_targets()
28-
pyocd_version = list_targets['pyocd_version']
29248
targets = list_targets['targets']
30-
print(pyocd_version)
31249
for target in targets:
32250
# print(target['name'])
33-
self.ui.targets_comboBox.addItem(target['name'])
251+
self.targets_comboBox.addItem(target['name'])
252+
253+
# def click_install_pack(self):
254+
# pack_file_path, _ = QFileDialog.getOpenFileName(self, "选择pack文件",self.file_path or os.getcwd(),'(*.pack)')
255+
# print(pack_file_path)
256+
# # self.file_lineEdit.setText(self.file_path)
34257

35-
def usb_selection(self):
36-
self.usb_probe()
37-
38258
def file_selection_button_click(self):
39-
self.file_path, _ = QFileDialog.getOpenFileName(self, "选择下载文件",self.file_path or os.getcwd(),'(*.bin *.hex *.elf *.axf)')
40-
self.ui.file_lineEdit.setText(self.file_path)
259+
self.file_path, _ = QFileDialog.getOpenFileName(self, "选择烧录文件",self.file_path or os.getcwd(),'(*.bin *.hex *.elf *.axf)')
260+
self.file_lineEdit.setText(self.file_path)
261+
41262
def usb_connect_button_click(self):
42-
print("usb_connect_button_click")
43-
if self.ui.usb_comboBox.currentText():
263+
# print("usb_connect_button_click")
264+
if self.usb_comboBox.currentText():
44265
if self.session and self.session.is_open:
45266
self.session.close()
46-
self.ui.usb_connect_button.setText("连接")
47-
self.ui.usb_comboBox.setEnabled(True)
267+
self.usb_connect_button.setText("连接")
268+
self.usb_comboBox.setEnabled(True)
269+
self.logs_label.setText("已断开连接")
48270
else:
49271
for Probe in self.allProbes:
50-
if self.ui.usb_comboBox.currentText() == Probe.description:
272+
if self.usb_comboBox.currentText() == Probe.description:
51273
self.Probe = Probe
52274
break
53-
# print(self.ui.usb_comboBox.currentText())
275+
# print(self.usb_comboBox.currentText())
54276
print(Probe,Probe.unique_id)
55-
# print(self.ui.targets_comboBox.currentText())
56-
# print(self.frequency[self.ui.speed_comboBox.currentText()])
277+
# print(self.targets_comboBox.currentText())
278+
# print(self.frequency[self.speed_comboBox.currentText()])
57279
if self.Probe:
58-
self.session = ConnectHelper.session_with_chosen_probe(blocking=False, return_first=False, unique_id=self.Probe.unique_id,options = {"frequency": self.frequency[self.ui.speed_comboBox.currentText()], "target_override": self.ui.targets_comboBox.currentText()})
280+
self.session = ConnectHelper.session_with_chosen_probe(
281+
blocking=False,
282+
return_first=False,
283+
unique_id=self.Probe.unique_id,
284+
options = {"frequency": self.frequency[self.speed_comboBox.currentText()],
285+
"target_override": self.targets_comboBox.currentText()})
59286
if self.session:
60287
self.session.open()
61288
board = self.session.board
@@ -74,40 +301,68 @@ def usb_connect_button_click(self):
74301
print("menory map: ",memory_map)
75302
print("ram_region: ",ram_region)
76303
print("rom_region: ",rom_region)
77-
self.ui.usb_connect_button.setText("断开")
78-
self.ui.usb_comboBox.setEnabled(False)
304+
self.usb_connect_button.setText("断开")
305+
self.usb_comboBox.setEnabled(False)
306+
self.logs_label.setText("已连接")
307+
79308
def progress(self, Value):
80-
self.ui.flash_progressBar.setValue(Value*100)
309+
self.flash_progressBar.setValue(Value*100)
310+
if Value == 1:
311+
self.logs_label.setText("烧录完成")
312+
else:
313+
self.logs_label.setText("烧录中...")
314+
315+
def programmer_finished(self):
316+
print("programmer_finished")
317+
81318
def flash_button_click(self):
82-
print("flash_button_click")
83-
self.ui.flash_progressBar.reset()
319+
# print("flash_button_click")
320+
self.flash_progressBar.reset()
84321
if self.session and self.session.is_open :
85-
board = self.session.board
86-
target = board.target
87-
# Load firmware into device.
88-
FileProgrammer(self.session,chip_erase="auto",smart_flash=False,trust_crc=False,keep_unwritten=True,no_reset=True,progress = self.progress).program(self.file_path)
89-
# Reset
90-
target.reset_and_halt()
322+
self.thread_programmer = Thread2(programmer,self)
323+
self.thread_programmer.finish.connect(self.programmer_finished)
324+
self.thread_programmer.start()
91325

92326
def usb_probe(self):
93327
self.allProbes = ConnectHelper.get_all_connected_probes(False, None, False)
94-
self.ui.usb_comboBox.clear()
328+
self.usb_comboBox.clear()
95329
if self.allProbes is None or len(self.allProbes) == 0:
96-
print("No Probe",self.allProbes)
330+
pass
331+
# print("No Probe",self.allProbes)
332+
return
97333
else:
98334
# print(self.allProbes)
99335
for Probe in self.allProbes:
100336
print(Probe)
101337
print(Probe.description)
102338
print(Probe.unique_id)
103-
self.ui.usb_comboBox.addItem(Probe.description)
339+
self.usb_comboBox.addItem(Probe.description)
340+
341+
def click_about(self):
342+
about_Dialog = QDialog(self)
343+
about_Dialog.resize(200, 200)
344+
about_Dialog.setMinimumSize(QSize(200, 200))
345+
about_Dialog.setMaximumSize(QSize(200, 200))
346+
about_Dialog.setWindowTitle("关于")
347+
icon = QIcon(icon_path)
348+
about_Dialog.setWindowIcon(icon)
349+
350+
about_label = QLabel(about_Dialog)
351+
about_label.setObjectName(u"about_label")
352+
about_label.setGeometry(QRect(0, 0, 200, 200))
353+
354+
about_label.setText(QCoreApplication.translate("MCUProg", mcuprog_tool_info, None))
104355

356+
about_Dialog.exec()
357+
358+
def click_exit(self):
359+
sys.exit(QApplication.instance().exec())
105360

106361

107362
if __name__ == '__main__':
108363
app = QApplication(sys.argv)
364+
app.setStyle("fusion")
109365
win = MainWindow()
110-
win.setWindowTitle("MCUProg")
111366
win.show()
112367
app.exit(app.exec())
113368

0 commit comments

Comments
 (0)