11import 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+
315from pyocd .core .helpers import ConnectHelper
416from pyocd .core .target import Target
517from pyocd .core .memory_map import MemoryType
618from pyocd .coresight .cortex_m import CortexM
719from pyocd .flash .file_programmer import FileProgrammer
820from 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+
1196class 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
107362if __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