├── doc └── main_window.png ├── .gitignore ├── README.md ├── flasher.py └── flasher_gui.py /doc/main_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/molejar/jlink-flasher/HEAD/doc/main_window.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | build 3 | 4 | flasher.spec 5 | flasher.cfg 6 | script.jlink 7 | mcu.db 8 | 9 | *.pyc 10 | 11 | # Intelij files 12 | .idea 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JLink Flasher 2 | ============= 3 | 4 | [SEGGER J-Links](http://segger.com/jlink-debug-probes.html) are the most widely used line of debug probes available today. Any of this J-Link 5 | debug probe can be also used as flash programmer, what can save you a lot of time and money in 6 | developing a new product. For this purpose exist Windows application [J-Flash](http://segger.com/jflash.html) developed by SEGGER, 7 | which can program internal and external flash on ARM/Cortex devices. Because I didn't found any 8 | similar tool for Linux, thus I have decided to create something useful by myself. And here is my first 9 | version of J-Link programmer GUI based on wxPython. 10 | 11 |

12 | JLink Flasher: main window 13 |

14 | 15 | -------------------------------------------------------------------------------- /flasher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import print_function 4 | 5 | import os, sys, wx 6 | import ConfigParser 7 | import subprocess 8 | import threading 9 | import platform 10 | import flasher_gui 11 | 12 | #wx.Log_EnableLogging() 13 | 14 | 15 | 16 | class JLink(object): 17 | def __init__(self): 18 | """ 19 | JLink control class 20 | 21 | """ 22 | if platform.system() is "Windows": 23 | self.os_type = "win" 24 | else: 25 | self.os_type = "linux" 26 | # 27 | self.pwd = os.path.dirname(os.path.realpath(sys.argv[0])) 28 | self.mcu_db_file = os.path.join(self.pwd, "mcu.db") 29 | self.script_file = os.path.join(self.pwd, "script.jlink") 30 | self.config_file = os.path.join(self.pwd, "flasher.cfg") 31 | self.supported_speeds = ["100", "200", "400", "800", "1000"] 32 | self.supported_interfaces = ["JTAG", "SWD"] 33 | # Configurable var. 34 | self.app_file = "" 35 | self.supported_chips = [] 36 | self.LoadConfig() 37 | 38 | 39 | def __del__(self): 40 | pass 41 | 42 | def LoadConfig(self): 43 | config = ConfigParser.ConfigParser() 44 | if config.read(self.config_file): 45 | self.app_file = config.get('Settings', 'app_file') 46 | self.supported_chips = config.get('Settings', 'usr_chips').split(', ') 47 | return True 48 | else: 49 | self.app_file = "Set The JLink.exe path" 50 | self.supported_chips = ["MKL25Z128xxx4", "MKL46Z256xxx4"] 51 | return False 52 | 53 | 54 | def SaveConfig(self): 55 | config = ConfigParser.ConfigParser() 56 | config.add_section("Settings") 57 | config.set('Settings', 'app_file', self.app_file) 58 | config.set('Settings', 'usr_chips', ', '.join(self.supported_chips)) 59 | # Writing our configuration file to 'example.cfg' 60 | with open(self.config_file, 'wb') as configfile: 61 | config.write(configfile) 62 | configfile.close() 63 | 64 | 65 | def BuildScript(self, cmd_type, chip_type, interface=1, speed='100', image=None, offset='0x00000000'): 66 | with open(self.script_file, 'w') as jsc_file: 67 | jsc_file.write('si ' + str(interface) + '\n') 68 | jsc_file.write('speed ' + self.supported_speeds[speed] + '\n') 69 | jsc_file.write('device ' + chip_type + '\n') 70 | 71 | if cmd_type == 'Erase': 72 | jsc_file.write('erase\n') 73 | elif cmd_type == 'Unlock': 74 | jsc_file.write('unlock kinetis\n') 75 | elif cmd_type == 'Program': 76 | #jsc_file.write('erase\n') 77 | jsc_file.write('loadbin ' + image + ', ' + offset + '\n') 78 | else: 79 | print("BuildScript: Unsuported CMD") 80 | 81 | jsc_file.write('r\n') 82 | jsc_file.write('exit\n') 83 | jsc_file.close() 84 | return True 85 | 86 | 87 | def UpdateChipsColection(self): 88 | with open(self.script_file, 'w') as jsc_file: 89 | jsc_file.write('ExpDevList ' + self.mcu_db_file + '\n') 90 | jsc_file.write('exit\n') 91 | jsc_file.close() 92 | # Clear file if exist 93 | fd = open(self.mcu_db_file, 'w') 94 | fd.close() 95 | 96 | # Execute JLinkExe and generate supported MCU collection 97 | subprocess.call("\"" + self.app_file + "\"" + " -CommanderScript " + self.script_file, shell=True) 98 | return True 99 | 100 | 101 | def LoadChipsColection(self): 102 | mcu_db = [] 103 | if os.path.isfile(self.mcu_db_file) and os.access(self.mcu_db_file, os.R_OK): 104 | with open(self.mcu_db_file, 'r') as fd_r: 105 | lines = fd_r.readlines() 106 | fd_r.close() 107 | for line in lines[1:]: 108 | line = line.strip('\r\n') 109 | line = line.replace('"', '') 110 | data = line.split(', ', 3) 111 | mcu_db.append((data[0], data[1], data[2])) 112 | return mcu_db 113 | 114 | 115 | 116 | class SettingsGUI(flasher_gui.ConfigDialog): 117 | def __init__(self, parent, jlink): 118 | flasher_gui.ConfigDialog.__init__(self, parent) 119 | self.jlink = jlink 120 | if self.jlink.app_file != "": 121 | self.m_textCtrl_jlink_path.SetValue(self.jlink.app_file) 122 | self.m_button_db_update.Enable(True) 123 | self.m_gauge_status.Enable(True) 124 | self.m_textCtrl_db_info.Enable(True) 125 | if os.path.isfile(self.jlink.mcu_db_file): 126 | self.m_textCtrl_db_info.Value = "OK" 127 | self.m_textCtrl_db_info.SetBackgroundColour(wx.Colour(200, 250, 160)) 128 | 129 | def __del__(self): 130 | pass 131 | 132 | def OnSelectDir(self, event): 133 | if self.jlink.os_type is "win": 134 | file_filter = "JLink.exe |JLink.exe" 135 | else: 136 | file_filter = "JLinkExe |JLinkExe" 137 | path = wx.FileDialog(self, "Found JLink Install Dir", 138 | os.path.dirname(self.m_textCtrl_jlink_path.Value), 139 | "", file_filter, wx.FD_FILE_MUST_EXIST) 140 | if path.ShowModal() == wx.ID_OK: 141 | self.jlink.app_file = path.Path 142 | self.m_textCtrl_jlink_path.SetValue(path.Path) 143 | self.m_button_db_update.Enable(True) 144 | self.m_gauge_status.Enable(True) 145 | self.m_textCtrl_db_info.Enable(True) 146 | 147 | event.Skip() 148 | 149 | def OnUpdateDB(self, event): 150 | self.m_gauge_status.SetValue(40) 151 | self.m_gauge_status.Update() 152 | if self.jlink.UpdateChipsColection() is True: 153 | self.m_gauge_status.SetValue(100) 154 | self.m_gauge_status.Update() 155 | self.m_textCtrl_db_info.Value = "OK" 156 | self.m_textCtrl_db_info.SetBackgroundColour(wx.Colour(200, 250, 160)) 157 | else: 158 | self.m_textCtrl_db_info.Value = "ERROR" 159 | self.m_textCtrl_db_info.SetBackgroundColour(wx.Colour(250, 200, 100)) 160 | event.Skip() 161 | 162 | 163 | class AddGUI(flasher_gui.TargetDialog): 164 | def __init__(self, parent, jlink): 165 | flasher_gui.TargetDialog.__init__(self, parent) 166 | self.jlink = jlink 167 | 168 | self.m_choice_vendor.AppendItems(["All", 169 | "Actel", 170 | "Analog", 171 | "Atmel", 172 | "Cypress", 173 | "Energy Micro", 174 | "Freescale", 175 | "Fujitsu", 176 | "Luminary", 177 | "Microchip", 178 | "Nordic Semi", 179 | "Nuvoton", 180 | "NXP", 181 | "Renesas", 182 | "Samsung", 183 | "Silicon Labs", 184 | "ST", 185 | "TI", 186 | "Toshiba"]) 187 | self.m_choice_vendor.SetSelection(0) 188 | self.m_choice_core.AppendItems(["All", 189 | "Cortex-M0", 190 | "Cortex-M3", 191 | "Cortex-M4", 192 | "Cortex-R4", 193 | "ARM966E-S", 194 | "Cortex-A9"]) 195 | self.m_choice_core.SetSelection(0) 196 | self.LoadSupportedChips("All", "All") 197 | self.LoadUsrChips() 198 | 199 | def __del__(self): 200 | pass 201 | 202 | def OnVendorChoice(self, event): 203 | self.LoadSupportedChips(self.m_choice_vendor.GetStringSelection(), self.m_choice_core.GetStringSelection()) 204 | event.Skip() 205 | 206 | 207 | def OnCoreChoice(self, event): 208 | self.LoadSupportedChips(self.m_choice_vendor.GetStringSelection(), self.m_choice_core.GetStringSelection()) 209 | event.Skip() 210 | 211 | def OnAdd( self, event ): 212 | index = self.m_listCtrl_mcu_db.GetFirstSelected() 213 | item = self.m_listCtrl_mcu_db.GetItem(index, 1).GetText() 214 | self.m_listCtrl_usr_db.InsertStringItem(self.m_listCtrl_usr_db.GetItemCount(), item) 215 | event.Skip() 216 | 217 | def OnDelete( self, event ): 218 | index = self.m_listCtrl_usr_db.GetFirstSelected() 219 | self.m_listCtrl_usr_db.DeleteItem(index) 220 | event.Skip() 221 | 222 | 223 | def LoadSupportedChips(self, vendor, core): 224 | self.m_listCtrl_mcu_db.ClearAll() 225 | self.m_listCtrl_mcu_db.InsertColumn(0, "Vendor", width=160) 226 | self.m_listCtrl_mcu_db.InsertColumn(1, "Device", width=250) 227 | self.m_listCtrl_mcu_db.InsertColumn(2, "Core", width=150) 228 | mcu_db = self.jlink.LoadChipsColection() 229 | if mcu_db != []: 230 | for item in mcu_db: 231 | if (vendor == "All" or item[0] == vendor) and (core == "All" or item[2] == core): 232 | self.m_listCtrl_mcu_db.Append(item) 233 | 234 | def LoadUsrChips(self): 235 | self.m_listCtrl_usr_db.ClearAll() 236 | self.m_listCtrl_usr_db.InsertColumn(0, "Device", width=560) 237 | for item in self.jlink.supported_chips: 238 | self.m_listCtrl_usr_db.Append([item]) 239 | 240 | 241 | class FlasherGUI(flasher_gui.AppFrame): 242 | def __init__(self, parent): 243 | flasher_gui.AppFrame.__init__(self, parent) 244 | 245 | self.jlink = JLink() 246 | 247 | self.m_choice_target.AppendItems(self.jlink.supported_chips) 248 | self.m_choice_target.SetSelection(0) 249 | self.m_choice_dbg_interface.AppendItems(self.jlink.supported_interfaces) 250 | self.m_choice_dbg_interface.SetSelection(1) 251 | for n in self.jlink.supported_speeds: 252 | self.m_choice_speed.Append(n + ' kHz') 253 | self.m_choice_speed.SetSelection(4) 254 | #self.m_textCtrl_log.AppendText(self.jlink.pwd) 255 | 256 | def __del__(self): 257 | pass 258 | 259 | def OnOpen(self, event): 260 | event.Skip() 261 | 262 | def OnSave(self, event): 263 | event.Skip() 264 | 265 | def OnExit(self, event): 266 | exit() 267 | 268 | def OnSettings(self, event): 269 | m_setting_dialog = SettingsGUI(parent=None, jlink=self.jlink) 270 | if m_setting_dialog.ShowModal() == wx.ID_CANCEL: 271 | self.m_textCtrl_log.AppendText("OK\n") 272 | self.jlink.app_file = m_setting_dialog.m_textCtrl_jlink_path.Value 273 | self.jlink.SaveConfig() 274 | m_setting_dialog.Destroy() 275 | event.Skip() 276 | 277 | def OnAbout(self, event): 278 | info = wx.AboutDialogInfo() 279 | info.Name = "JLink Flasher" 280 | info.Version = "0.0.1 Beta" 281 | info.Copyright = "(C) 2014 Martin Olejar" 282 | info.WebSite = ("http://www.segger.com", "SEGGER Home Page") 283 | wx.AboutBox(info) 284 | event.Skip() 285 | 286 | def OnTargetAdd(self, event): 287 | m_add_dialog = AddGUI(parent=None, jlink=self.jlink) 288 | if m_add_dialog.ShowModal() == wx.ID_OK: 289 | self.m_choice_target.Clear() 290 | i = 0 291 | self.jlink.supported_chips = [] 292 | while i < m_add_dialog.m_listCtrl_usr_db.GetItemCount(): 293 | item = m_add_dialog.m_listCtrl_usr_db.GetItem(i, 0).GetText() 294 | self.m_choice_target.Append(item) 295 | self.jlink.supported_chips.append(item) 296 | i += 1 297 | self.m_choice_target.SetSelection(0) 298 | self.jlink.SaveConfig() 299 | m_add_dialog.Destroy() 300 | event.Skip() 301 | 302 | def OnImageUpdated(self, event): 303 | if os.path.exists(self.m_filePicker_targetImage.Path): 304 | self.m_button_flash.Enable(True) 305 | self.m_textCtrl_offset.Enable(True) 306 | else: 307 | self.m_button_flash.Enable(False) 308 | self.m_textCtrl_offset.Enable(False) 309 | event.Skip() 310 | 311 | def OnLogEnable(self, event): 312 | if self.m_textCtrl_log.IsShown: 313 | self.m_textCtrl_log.Hide() 314 | else: 315 | self.m_textCtrl_log.Shown() 316 | event.Skip() 317 | 318 | def OnResetTarget(self, event): 319 | self.Execute('Reset') 320 | event.Skip() 321 | 322 | def OnUnlockTarget(self, event): 323 | self.Execute('Unlock') 324 | event.Skip() 325 | 326 | def OnEraseTarget(self, event): 327 | self.Execute('Erase') 328 | event.Skip() 329 | 330 | def OnFlashTarget(self, event): 331 | self.Execute('Program') 332 | event.Skip() 333 | 334 | def Execute(self, cmd): 335 | self.m_textCtrl_log.Clear() 336 | self.m_textCtrl_log.AppendText("\n<<<< " + cmd + " Target >>>> \n\n") 337 | status = self.jlink.BuildScript(cmd_type=cmd, 338 | chip_type=self.m_choice_target.GetStringSelection(), 339 | interface=self.m_choice_dbg_interface.GetSelection(), 340 | speed=self.m_choice_speed.GetSelection(), 341 | image=self.m_filePicker_targetImage.Path, 342 | offset=self.m_textCtrl_offset.Value) 343 | if status is True: 344 | try: 345 | thread = threading.Thread(target=self.run) 346 | thread.setDaemon(True) 347 | thread.start() 348 | except: 349 | self.m_textCtrl_log.AppendText("\n<<<< " + cmd + " Error >>>> \n") 350 | 351 | 352 | def run(self): 353 | for line in subprocess.Popen("\"" + self.jlink.app_file + "\"" + " -CommanderScript " + self.jlink.script_file, 354 | shell=True, 355 | stdout=subprocess.PIPE, 356 | stderr=subprocess.STDOUT).stdout: 357 | wx.CallAfter(self.m_textCtrl_log.AppendText, line) 358 | 359 | 360 | class MyApp(wx.App): 361 | def OnInit(self): 362 | frame = FlasherGUI(None) 363 | frame.Show(True) 364 | return True 365 | 366 | 367 | if __name__ == '__main__': 368 | app = MyApp(0) 369 | app.MainLoop() 370 | -------------------------------------------------------------------------------- /flasher_gui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ########################################################################### 4 | ## Python code generated with wxFormBuilder (version Jun 5 2014) 5 | ## http://www.wxformbuilder.org/ 6 | ## 7 | ## PLEASE DO "NOT" EDIT THIS FILE! 8 | ########################################################################### 9 | 10 | import wx 11 | import wx.xrc 12 | 13 | ########################################################################### 14 | ## Class AppFrame 15 | ########################################################################### 16 | 17 | class AppFrame ( wx.Frame ): 18 | 19 | def __init__( self, parent ): 20 | wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"JLink Flasher", pos = wx.DefaultPosition, size = wx.Size( 550,500 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL ) 21 | 22 | self.SetSizeHintsSz( wx.Size( 550,500 ), wx.DefaultSize ) 23 | self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_MENU ) ) 24 | 25 | self.m_menubar = wx.MenuBar( 0 ) 26 | self.m_menu_file = wx.Menu() 27 | self.m_menuItem_exit = wx.MenuItem( self.m_menu_file, wx.ID_ANY, u"&Exit"+ u"\t" + u"CTRL+X", wx.EmptyString, wx.ITEM_NORMAL ) 28 | self.m_menuItem_exit.SetBitmap( wx.ArtProvider.GetBitmap( wx.ART_QUIT, ) ) 29 | self.m_menu_file.AppendItem( self.m_menuItem_exit ) 30 | 31 | self.m_menubar.Append( self.m_menu_file, u"&File" ) 32 | 33 | self.m_menu_tools = wx.Menu() 34 | self.m_menuItem_settings = wx.MenuItem( self.m_menu_tools, wx.ID_ANY, u"&Settings"+ u"\t" + u"CTRL+S", wx.EmptyString, wx.ITEM_NORMAL ) 35 | self.m_menuItem_settings.SetBitmap( wx.NullBitmap ) 36 | self.m_menu_tools.AppendItem( self.m_menuItem_settings ) 37 | 38 | self.m_menubar.Append( self.m_menu_tools, u"&Tools" ) 39 | 40 | self.m_menu_help = wx.Menu() 41 | self.m_menuItem_about = wx.MenuItem( self.m_menu_help, wx.ID_ANY, u"&About.."+ u"\t" + u"F1", wx.EmptyString, wx.ITEM_NORMAL ) 42 | self.m_menuItem_about.SetBitmap( wx.ArtProvider.GetBitmap( wx.ART_HELP_FOLDER, ) ) 43 | self.m_menu_help.AppendItem( self.m_menuItem_about ) 44 | 45 | self.m_menubar.Append( self.m_menu_help, u"&Help" ) 46 | 47 | self.SetMenuBar( self.m_menubar ) 48 | 49 | fgSizer = wx.FlexGridSizer( 2, 1, 0, 0 ) 50 | fgSizer.AddGrowableCol( 0 ) 51 | fgSizer.AddGrowableRow( 0 ) 52 | fgSizer.SetFlexibleDirection( wx.BOTH ) 53 | fgSizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) 54 | 55 | self.m_panel2 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL ) 56 | self.m_panel2.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_MENU ) ) 57 | 58 | fgSizer31 = wx.FlexGridSizer( 4, 1, 0, 0 ) 59 | fgSizer31.AddGrowableCol( 0 ) 60 | fgSizer31.AddGrowableRow( 2 ) 61 | fgSizer31.SetFlexibleDirection( wx.BOTH ) 62 | fgSizer31.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) 63 | 64 | fgSizer3 = wx.FlexGridSizer( 3, 2, 0, 0 ) 65 | fgSizer3.AddGrowableCol( 1 ) 66 | fgSizer3.SetFlexibleDirection( wx.BOTH ) 67 | fgSizer3.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) 68 | 69 | self.m_staticText1 = wx.StaticText( self.m_panel2, wx.ID_ANY, u"Target:", wx.DefaultPosition, wx.DefaultSize, 0 ) 70 | self.m_staticText1.Wrap( -1 ) 71 | fgSizer3.Add( self.m_staticText1, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 72 | 73 | bSizer6 = wx.BoxSizer( wx.HORIZONTAL ) 74 | 75 | m_choice_targetChoices = [] 76 | self.m_choice_target = wx.Choice( self.m_panel2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice_targetChoices, wx.CB_SORT ) 77 | self.m_choice_target.SetSelection( 0 ) 78 | self.m_choice_target.SetFont( wx.Font( 9, 74, 90, 90, False, "Sans" ) ) 79 | self.m_choice_target.SetToolTipString( u"Select Target MCU" ) 80 | 81 | bSizer6.Add( self.m_choice_target, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.BOTTOM|wx.LEFT, 5 ) 82 | 83 | self.m_button_add = wx.Button( self.m_panel2, wx.ID_ANY, u"Add", wx.DefaultPosition, wx.DefaultSize, 0 ) 84 | self.m_button_add.SetFont( wx.Font( 9, 74, 90, 92, False, "Sans" ) ) 85 | 86 | bSizer6.Add( self.m_button_add, 0, wx.ALL, 5 ) 87 | 88 | 89 | fgSizer3.Add( bSizer6, 1, wx.EXPAND, 5 ) 90 | 91 | self.m_staticText2 = wx.StaticText( self.m_panel2, wx.ID_ANY, u"Image:", wx.DefaultPosition, wx.DefaultSize, 0 ) 92 | self.m_staticText2.Wrap( -1 ) 93 | fgSizer3.Add( self.m_staticText2, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 94 | 95 | self.m_filePicker_targetImage = wx.FilePickerCtrl( self.m_panel2, wx.ID_ANY, wx.EmptyString, u"Select a file", u"BIN files (*.bin)|*.bin|HEX files (*.hex)|*.hex", wx.DefaultPosition, wx.DefaultSize, wx.FLP_DEFAULT_STYLE ) 96 | self.m_filePicker_targetImage.SetFont( wx.Font( 9, 74, 90, 90, False, "Sans" ) ) 97 | 98 | fgSizer3.Add( self.m_filePicker_targetImage, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 5 ) 99 | 100 | self.m_staticText_offset = wx.StaticText( self.m_panel2, wx.ID_ANY, u"Offset:", wx.DefaultPosition, wx.DefaultSize, 0 ) 101 | self.m_staticText_offset.Wrap( -1 ) 102 | fgSizer3.Add( self.m_staticText_offset, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 103 | 104 | bSizer9 = wx.BoxSizer( wx.HORIZONTAL ) 105 | 106 | self.m_textCtrl_offset = wx.TextCtrl( self.m_panel2, wx.ID_ANY, u"0x00000000", wx.DefaultPosition, wx.DefaultSize, 0 ) 107 | self.m_textCtrl_offset.SetFont( wx.Font( 9, 74, 90, 90, False, "Sans" ) ) 108 | self.m_textCtrl_offset.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_WINDOW ) ) 109 | self.m_textCtrl_offset.Enable( False ) 110 | self.m_textCtrl_offset.SetToolTipString( u"Set Image Offset" ) 111 | self.m_textCtrl_offset.SetMinSize( wx.Size( 100,-1 ) ) 112 | 113 | bSizer9.Add( self.m_textCtrl_offset, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5 ) 114 | 115 | 116 | bSizer9.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 ) 117 | 118 | self.m_staticText8 = wx.StaticText( self.m_panel2, wx.ID_ANY, u"Bus Type:", wx.DefaultPosition, wx.DefaultSize, 0 ) 119 | self.m_staticText8.Wrap( -1 ) 120 | bSizer9.Add( self.m_staticText8, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 121 | 122 | m_choice_dbg_interfaceChoices = [] 123 | self.m_choice_dbg_interface = wx.Choice( self.m_panel2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice_dbg_interfaceChoices, 0 ) 124 | self.m_choice_dbg_interface.SetSelection( 0 ) 125 | self.m_choice_dbg_interface.SetMinSize( wx.Size( 110,-1 ) ) 126 | 127 | bSizer9.Add( self.m_choice_dbg_interface, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5 ) 128 | 129 | 130 | bSizer9.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 ) 131 | 132 | self.m_staticText7 = wx.StaticText( self.m_panel2, wx.ID_ANY, u"Speed:", wx.DefaultPosition, wx.DefaultSize, 0 ) 133 | self.m_staticText7.Wrap( -1 ) 134 | bSizer9.Add( self.m_staticText7, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 135 | 136 | m_choice_speedChoices = [] 137 | self.m_choice_speed = wx.Choice( self.m_panel2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice_speedChoices, 0 ) 138 | self.m_choice_speed.SetSelection( 0 ) 139 | self.m_choice_speed.SetMinSize( wx.Size( 120,-1 ) ) 140 | 141 | bSizer9.Add( self.m_choice_speed, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5 ) 142 | 143 | 144 | fgSizer3.Add( bSizer9, 1, wx.EXPAND, 5 ) 145 | 146 | 147 | fgSizer31.Add( fgSizer3, 1, wx.EXPAND|wx.ALL, 5 ) 148 | 149 | bSizer3 = wx.BoxSizer( wx.HORIZONTAL ) 150 | 151 | self.m_staticline3 = wx.StaticLine( self.m_panel2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) 152 | bSizer3.Add( self.m_staticline3, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 153 | 154 | self.m_staticText5 = wx.StaticText( self.m_panel2, wx.ID_ANY, u"<< Log >>", wx.DefaultPosition, wx.DefaultSize, 0 ) 155 | self.m_staticText5.Wrap( -1 ) 156 | self.m_staticText5.SetForegroundColour( wx.Colour( 80, 80, 80 ) ) 157 | 158 | bSizer3.Add( self.m_staticText5, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 159 | 160 | self.m_staticline1 = wx.StaticLine( self.m_panel2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) 161 | self.m_staticline1.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_WINDOW ) ) 162 | 163 | bSizer3.Add( self.m_staticline1, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) 164 | 165 | 166 | fgSizer31.Add( bSizer3, 1, wx.EXPAND|wx.RIGHT|wx.LEFT, 5 ) 167 | 168 | bSizer4 = wx.BoxSizer( wx.VERTICAL ) 169 | 170 | self.m_textCtrl_log = wx.TextCtrl( self.m_panel2, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.TE_CHARWRAP|wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_WORDWRAP ) 171 | self.m_textCtrl_log.SetForegroundColour( wx.Colour( 15, 228, 100 ) ) 172 | self.m_textCtrl_log.SetBackgroundColour( wx.Colour( 0, 0, 0 ) ) 173 | 174 | bSizer4.Add( self.m_textCtrl_log, 1, wx.EXPAND, 12 ) 175 | 176 | 177 | fgSizer31.Add( bSizer4, 1, wx.EXPAND|wx.RIGHT|wx.LEFT, 12 ) 178 | 179 | bSizer2 = wx.BoxSizer( wx.HORIZONTAL ) 180 | 181 | self.m_button_unlock = wx.Button( self.m_panel2, wx.ID_ANY, u"Unlock", wx.DefaultPosition, wx.DefaultSize, 0 ) 182 | self.m_button_unlock.SetFont( wx.Font( 9, 74, 90, 92, False, "Sans" ) ) 183 | 184 | bSizer2.Add( self.m_button_unlock, 0, wx.ALL, 5 ) 185 | 186 | 187 | bSizer2.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 ) 188 | 189 | self.m_button_reset = wx.Button( self.m_panel2, wx.ID_ANY, u"Reset", wx.DefaultPosition, wx.DefaultSize, 0 ) 190 | self.m_button_reset.SetFont( wx.Font( 9, 74, 90, 92, False, "Sans" ) ) 191 | 192 | bSizer2.Add( self.m_button_reset, 0, wx.ALL, 5 ) 193 | 194 | 195 | bSizer2.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 ) 196 | 197 | self.m_button_erase = wx.Button( self.m_panel2, wx.ID_ANY, u"Erase", wx.DefaultPosition, wx.DefaultSize, 0 ) 198 | self.m_button_erase.SetFont( wx.Font( 9, 74, 90, 92, False, "Sans" ) ) 199 | 200 | bSizer2.Add( self.m_button_erase, 0, wx.ALL, 5 ) 201 | 202 | 203 | bSizer2.AddSpacer( ( 0, 0), 1, wx.EXPAND, 5 ) 204 | 205 | self.m_button_flash = wx.Button( self.m_panel2, wx.ID_ANY, u"Flash", wx.DefaultPosition, wx.DefaultSize, 0 ) 206 | self.m_button_flash.SetFont( wx.Font( 9, 74, 90, 92, False, "Sans" ) ) 207 | self.m_button_flash.Enable( False ) 208 | 209 | bSizer2.Add( self.m_button_flash, 0, wx.ALL, 5 ) 210 | 211 | 212 | fgSizer31.Add( bSizer2, 1, wx.EXPAND|wx.TOP|wx.RIGHT|wx.LEFT, 6 ) 213 | 214 | 215 | self.m_panel2.SetSizer( fgSizer31 ) 216 | self.m_panel2.Layout() 217 | fgSizer31.Fit( self.m_panel2 ) 218 | fgSizer.Add( self.m_panel2, 0, wx.EXPAND |wx.ALL, 5 ) 219 | 220 | 221 | self.SetSizer( fgSizer ) 222 | self.Layout() 223 | self.m_statusBar = self.CreateStatusBar( 1, wx.ST_SIZEGRIP, wx.ID_ANY ) 224 | 225 | self.Centre( wx.BOTH ) 226 | 227 | # Connect Events 228 | self.Bind( wx.EVT_MENU, self.OnExit, id = self.m_menuItem_exit.GetId() ) 229 | self.Bind( wx.EVT_MENU, self.OnSettings, id = self.m_menuItem_settings.GetId() ) 230 | self.Bind( wx.EVT_MENU, self.OnAbout, id = self.m_menuItem_about.GetId() ) 231 | self.m_button_add.Bind( wx.EVT_BUTTON, self.OnTargetAdd ) 232 | self.m_filePicker_targetImage.Bind( wx.EVT_FILEPICKER_CHANGED, self.OnImageUpdated ) 233 | self.m_button_unlock.Bind( wx.EVT_BUTTON, self.OnUnlockTarget ) 234 | self.m_button_reset.Bind( wx.EVT_BUTTON, self.OnResetTarget ) 235 | self.m_button_erase.Bind( wx.EVT_BUTTON, self.OnEraseTarget ) 236 | self.m_button_flash.Bind( wx.EVT_BUTTON, self.OnFlashTarget ) 237 | 238 | def __del__( self ): 239 | pass 240 | 241 | 242 | # Virtual event handlers, overide them in your derived class 243 | def OnExit( self, event ): 244 | event.Skip() 245 | 246 | def OnSettings( self, event ): 247 | event.Skip() 248 | 249 | def OnAbout( self, event ): 250 | event.Skip() 251 | 252 | def OnTargetAdd( self, event ): 253 | event.Skip() 254 | 255 | def OnImageUpdated( self, event ): 256 | event.Skip() 257 | 258 | def OnUnlockTarget( self, event ): 259 | event.Skip() 260 | 261 | def OnResetTarget( self, event ): 262 | event.Skip() 263 | 264 | def OnEraseTarget( self, event ): 265 | event.Skip() 266 | 267 | def OnFlashTarget( self, event ): 268 | event.Skip() 269 | 270 | 271 | ########################################################################### 272 | ## Class ConfigDialog 273 | ########################################################################### 274 | 275 | class ConfigDialog ( wx.Dialog ): 276 | 277 | def __init__( self, parent ): 278 | wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Flasher Settings", pos = wx.DefaultPosition, size = wx.Size( 480,160 ), style = wx.DEFAULT_DIALOG_STYLE|wx.STAY_ON_TOP ) 279 | 280 | self.SetSizeHintsSz( wx.Size( -1,-1 ), wx.DefaultSize ) 281 | 282 | bSizer9 = wx.BoxSizer( wx.VERTICAL ) 283 | 284 | fgSizer5 = wx.FlexGridSizer( 3, 2, 0, 0 ) 285 | fgSizer5.AddGrowableCol( 1 ) 286 | fgSizer5.SetFlexibleDirection( wx.BOTH ) 287 | fgSizer5.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) 288 | 289 | self.m_staticText4 = wx.StaticText( self, wx.ID_ANY, u"JLink Path:", wx.DefaultPosition, wx.DefaultSize, 0 ) 290 | self.m_staticText4.Wrap( -1 ) 291 | fgSizer5.Add( self.m_staticText4, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 292 | 293 | bSizer10 = wx.BoxSizer( wx.HORIZONTAL ) 294 | 295 | self.m_textCtrl_jlink_path = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_READONLY ) 296 | self.m_textCtrl_jlink_path.SetMinSize( wx.Size( -1,26 ) ) 297 | 298 | bSizer10.Add( self.m_textCtrl_jlink_path, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) 299 | 300 | self.m_bt_jlink_path = wx.Button( self, wx.ID_ANY, u"...", wx.DefaultPosition, wx.DefaultSize, 0 ) 301 | bSizer10.Add( self.m_bt_jlink_path, 0, wx.ALL, 5 ) 302 | 303 | 304 | fgSizer5.Add( bSizer10, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5 ) 305 | 306 | self.m_staticText6 = wx.StaticText( self, wx.ID_ANY, u"MCU DB:", wx.DefaultPosition, wx.DefaultSize, 0 ) 307 | self.m_staticText6.Wrap( -1 ) 308 | fgSizer5.Add( self.m_staticText6, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 309 | 310 | bSizer5 = wx.BoxSizer( wx.HORIZONTAL ) 311 | 312 | self.m_textCtrl_db_info = wx.TextCtrl( self, wx.ID_ANY, u"NA", wx.DefaultPosition, wx.Size( -1,25 ), wx.TE_CENTRE|wx.TE_READONLY ) 313 | self.m_textCtrl_db_info.SetBackgroundColour( wx.Colour( 251, 210, 160 ) ) 314 | self.m_textCtrl_db_info.Enable( False ) 315 | 316 | bSizer5.Add( self.m_textCtrl_db_info, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 317 | 318 | self.m_gauge_status = wx.Gauge( self, wx.ID_ANY, 100, wx.DefaultPosition, wx.Size( -1,25 ), wx.GA_HORIZONTAL ) 319 | self.m_gauge_status.SetValue( 0 ) 320 | self.m_gauge_status.Enable( False ) 321 | 322 | bSizer5.Add( self.m_gauge_status, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 323 | 324 | self.m_button_db_update = wx.Button( self, wx.ID_ANY, u"Update", wx.DefaultPosition, wx.DefaultSize, 0 ) 325 | self.m_button_db_update.Enable( False ) 326 | 327 | bSizer5.Add( self.m_button_db_update, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 328 | 329 | 330 | fgSizer5.Add( bSizer5, 1, wx.EXPAND, 5 ) 331 | 332 | 333 | bSizer9.Add( fgSizer5, 1, wx.EXPAND|wx.TOP|wx.RIGHT|wx.LEFT, 5 ) 334 | 335 | self.m_staticline3 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) 336 | bSizer9.Add( self.m_staticline3, 0, wx.EXPAND|wx.BOTTOM|wx.RIGHT|wx.LEFT, 10 ) 337 | 338 | m_sdbSizer2 = wx.StdDialogButtonSizer() 339 | self.m_sdbSizer2Cancel = wx.Button( self, wx.ID_CANCEL ) 340 | m_sdbSizer2.AddButton( self.m_sdbSizer2Cancel ) 341 | m_sdbSizer2.Realize(); 342 | 343 | bSizer9.Add( m_sdbSizer2, 0, wx.ALIGN_RIGHT|wx.EXPAND|wx.BOTTOM|wx.RIGHT|wx.LEFT, 10 ) 344 | 345 | 346 | self.SetSizer( bSizer9 ) 347 | self.Layout() 348 | 349 | self.Centre( wx.BOTH ) 350 | 351 | # Connect Events 352 | self.m_bt_jlink_path.Bind( wx.EVT_BUTTON, self.OnSelectDir ) 353 | self.m_button_db_update.Bind( wx.EVT_BUTTON, self.OnUpdateDB ) 354 | 355 | def __del__( self ): 356 | pass 357 | 358 | 359 | # Virtual event handlers, overide them in your derived class 360 | def OnSelectDir( self, event ): 361 | event.Skip() 362 | 363 | def OnUpdateDB( self, event ): 364 | event.Skip() 365 | 366 | 367 | ########################################################################### 368 | ## Class TargetDialog 369 | ########################################################################### 370 | 371 | class TargetDialog ( wx.Dialog ): 372 | 373 | def __init__( self, parent ): 374 | wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Supported Targets", pos = wx.DefaultPosition, size = wx.Size( 600,500 ), style = wx.DEFAULT_DIALOG_STYLE|wx.STAY_ON_TOP ) 375 | 376 | self.SetSizeHintsSz( wx.Size( -1,-1 ), wx.DefaultSize ) 377 | 378 | bSizer_main = wx.BoxSizer( wx.VERTICAL ) 379 | 380 | self.m_splitter = wx.SplitterWindow( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.SP_3D|wx.SP_BORDER|wx.SP_LIVE_UPDATE ) 381 | self.m_splitter.SetSashGravity( 1 ) 382 | self.m_splitter.Bind( wx.EVT_IDLE, self.m_splitterOnIdle ) 383 | self.m_splitter.SetMinimumPaneSize( 2 ) 384 | 385 | self.m_panel_01 = wx.Panel( self.m_splitter, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL ) 386 | fgSizer1 = wx.FlexGridSizer( 2, 1, 0, 0 ) 387 | fgSizer1.AddGrowableCol( 0 ) 388 | fgSizer1.AddGrowableRow( 1 ) 389 | fgSizer1.SetFlexibleDirection( wx.BOTH ) 390 | fgSizer1.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) 391 | 392 | bSizer13 = wx.BoxSizer( wx.HORIZONTAL ) 393 | 394 | self.m_staticText_vendor = wx.StaticText( self.m_panel_01, wx.ID_ANY, u"Manufacturer:", wx.DefaultPosition, wx.DefaultSize, 0 ) 395 | self.m_staticText_vendor.Wrap( -1 ) 396 | bSizer13.Add( self.m_staticText_vendor, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 397 | 398 | m_choice_vendorChoices = [] 399 | self.m_choice_vendor = wx.Choice( self.m_panel_01, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice_vendorChoices, 0 ) 400 | self.m_choice_vendor.SetSelection( 0 ) 401 | bSizer13.Add( self.m_choice_vendor, 1, wx.ALL, 5 ) 402 | 403 | 404 | bSizer13.AddSpacer( ( 20, 0), 0, wx.ALIGN_CENTER_VERTICAL, 5 ) 405 | 406 | self.m_staticText_core = wx.StaticText( self.m_panel_01, wx.ID_ANY, u"MCU Core:", wx.DefaultPosition, wx.DefaultSize, 0 ) 407 | self.m_staticText_core.Wrap( -1 ) 408 | bSizer13.Add( self.m_staticText_core, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) 409 | 410 | m_choice_coreChoices = [] 411 | self.m_choice_core = wx.Choice( self.m_panel_01, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice_coreChoices, 0 ) 412 | self.m_choice_core.SetSelection( 0 ) 413 | bSizer13.Add( self.m_choice_core, 1, wx.ALL, 5 ) 414 | 415 | 416 | fgSizer1.Add( bSizer13, 1, wx.EXPAND|wx.TOP, 8 ) 417 | 418 | self.m_listCtrl_mcu_db = wx.ListCtrl( self.m_panel_01, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LC_AUTOARRANGE|wx.LC_NO_SORT_HEADER|wx.LC_REPORT ) 419 | fgSizer1.Add( self.m_listCtrl_mcu_db, 1, wx.EXPAND|wx.ALL, 5 ) 420 | 421 | 422 | self.m_panel_01.SetSizer( fgSizer1 ) 423 | self.m_panel_01.Layout() 424 | fgSizer1.Fit( self.m_panel_01 ) 425 | self.m_panel_02 = wx.Panel( self.m_splitter, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL ) 426 | fgSizer2 = wx.FlexGridSizer( 1, 1, 0, 0 ) 427 | fgSizer2.AddGrowableCol( 0 ) 428 | fgSizer2.AddGrowableRow( 0 ) 429 | fgSizer2.SetFlexibleDirection( wx.BOTH ) 430 | fgSizer2.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED ) 431 | 432 | self.m_listCtrl_usr_db = wx.ListCtrl( self.m_panel_02, wx.ID_ANY, wx.DefaultPosition, wx.Size( -1,-1 ), wx.LC_AUTOARRANGE|wx.LC_REPORT ) 433 | fgSizer2.Add( self.m_listCtrl_usr_db, 1, wx.EXPAND|wx.ALL, 5 ) 434 | 435 | 436 | self.m_panel_02.SetSizer( fgSizer2 ) 437 | self.m_panel_02.Layout() 438 | fgSizer2.Fit( self.m_panel_02 ) 439 | self.m_splitter.SplitHorizontally( self.m_panel_01, self.m_panel_02, 280 ) 440 | bSizer_main.Add( self.m_splitter, 1, wx.EXPAND|wx.RIGHT|wx.LEFT, 5 ) 441 | 442 | self.m_staticline = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL ) 443 | bSizer_main.Add( self.m_staticline, 0, wx.EXPAND|wx.RIGHT|wx.LEFT, 10 ) 444 | 445 | m_sdbSizer = wx.StdDialogButtonSizer() 446 | self.m_sdbSizerOK = wx.Button( self, wx.ID_OK ) 447 | m_sdbSizer.AddButton( self.m_sdbSizerOK ) 448 | self.m_sdbSizerCancel = wx.Button( self, wx.ID_CANCEL ) 449 | m_sdbSizer.AddButton( self.m_sdbSizerCancel ) 450 | m_sdbSizer.Realize(); 451 | 452 | bSizer_main.Add( m_sdbSizer, 0, wx.EXPAND|wx.ALL, 10 ) 453 | 454 | 455 | self.SetSizer( bSizer_main ) 456 | self.Layout() 457 | 458 | self.Centre( wx.BOTH ) 459 | 460 | # Connect Events 461 | self.m_choice_vendor.Bind( wx.EVT_CHOICE, self.OnVendorChoice ) 462 | self.m_choice_core.Bind( wx.EVT_CHOICE, self.OnCoreChoice ) 463 | self.m_listCtrl_mcu_db.Bind( wx.EVT_LEFT_DCLICK, self.OnAdd ) 464 | self.m_listCtrl_usr_db.Bind( wx.EVT_LEFT_DCLICK, self.OnDelete ) 465 | 466 | def __del__( self ): 467 | pass 468 | 469 | 470 | # Virtual event handlers, overide them in your derived class 471 | def OnVendorChoice( self, event ): 472 | event.Skip() 473 | 474 | def OnCoreChoice( self, event ): 475 | event.Skip() 476 | 477 | def OnAdd( self, event ): 478 | event.Skip() 479 | 480 | def OnDelete( self, event ): 481 | event.Skip() 482 | 483 | def m_splitterOnIdle( self, event ): 484 | self.m_splitter.SetSashPosition( 280 ) 485 | self.m_splitter.Unbind( wx.EVT_IDLE ) 486 | 487 | 488 | --------------------------------------------------------------------------------