1- import argparse , subprocess , os , sys , re , warnings
1+ import argparse , subprocess , os , sys , re , warnings , tempfile
22from serial .tools .list_ports import comports
33from xmc_data import xmc_master_data
44
5- version = '0.1.1 '
5+ version = '0.1.2 '
66
77jlinkexe = ''
88
9+ # Set temporary file for jlink command file and output file
10+ cmd_jlink = os .path .join (tempfile .gettempdir (), 'cmd.jlink' )
11+ console_out = os .path .join (tempfile .gettempdir (), 'console.output' )
12+
913def check_python_version ():
1014 major = sys .version_info .major
1115 minor = sys .version_info .minor
@@ -31,9 +35,7 @@ def set_environment():
3135 elif sys .platform == 'win32' or sys .platform == 'cygwin' :
3236 jlinkexe = rf"{ get_jlink_install_path ()} \jlink.exe"
3337 elif sys .platform == 'darwin' :
34- jlinkexe = 'jlink'
35- print ('warning: mac os not validated' )
36- #raise Exception('mac os not supported?')
38+ jlinkexe = 'JLinkExe'
3739
3840def discover_devices ():
3941 ports = comports ()
@@ -46,21 +48,18 @@ def discover_devices():
4648def get_device_serial_number (port ):
4749 port_sn_list = discover_devices ()
4850 for device in port_sn_list :
49- if device [0 ] == port :
50- return device [1 ]
51-
51+ if device [0 ] == port and device [0 ] != None :
52+ return device [1 ]
5253 return None
5354
5455def create_jlink_loadbin_command_file (binfile ):
55- cmd_jlink = 'cmd.jlink'
5656 cmd_load_bin = 'loadbin ' + binfile + ' 0x0\n '
5757 with open (cmd_jlink ,'w' ) as f :
5858 f .writelines (['r\n ' , 'h\n ' , cmd_load_bin , 'r\n ' , 'g\n ' , 'exit\n ' ])
5959
6060 return cmd_jlink
6161
6262def create_jlink_mem_read_command_file (addr , bytes ):
63- cmd_jlink = 'cmd.jlink'
6463 #cmd_log_enable
6564 cmd_mem_read = 'mem ' + addr + ', ' + bytes + '\n ' # todo: store register maps, bytes in file
6665 with open (cmd_jlink ,'w' ) as f :
@@ -69,7 +68,6 @@ def create_jlink_mem_read_command_file(addr, bytes):
6968 return cmd_jlink
7069
7170def create_jlink_erase_command_file ():
72- cmd_jlink = 'cmd.jlink'
7371 with open (cmd_jlink ,'w' ) as f :
7472 f .writelines (['r\n ' , 'h\n ' , 'erase\n ' , 'exit\n ' ])
7573
@@ -93,7 +91,7 @@ def jlink_commander(device, serial_num, cmd_file, console_output=False):
9391 jlink_proc = subprocess .Popen (jlink_cmd , stdout = subprocess .PIPE , universal_newlines = True )
9492 if console_output is True :
9593 out , err = jlink_proc .communicate ()
96- with open ('console.output' , 'w' ) as f :
94+ with open (console_out , 'w' ) as f :
9795 f .write (out )
9896 else :
9997 for line in jlink_proc .stdout :
@@ -103,26 +101,33 @@ def jlink_commander(device, serial_num, cmd_file, console_output=False):
103101 raise Exception ("jlink error" )
104102
105103def process_console_output (string ):
106- with open ('console.output' ,'r' ) as f :
104+ with open (console_out ,'r' ) as f :
107105 lines = f .readlines ()
108106 lines [0 ].split ('\n ' )
109107
110108 for line in lines :
111109 if string in line and '=' in line :
112110 print (line )
113111
112+ def check_serial_number (serial_num ):
113+ if serial_num == None :
114+ raise Exception ("Device not found! Please check the serial port" )
115+
114116def get_mem_contents (addr , bytes , device , port ):
115-
116- serial_num = get_device_serial_number (port )
117+ try :
118+ serial_num = get_device_serial_number (port )
119+ check_serial_number (serial_num )
120+ except ValueError as e :
121+ print (e )
117122 jlink_cmd_file = create_jlink_mem_read_command_file (addr , bytes ) # todo: comes from proper metafile
118123 jlink_commander (device , serial_num , jlink_cmd_file , True )
119124 remove_jlink_command_file (jlink_cmd_file )
120125
121- with open ('console.output' ,'r' ) as f :
126+ with open (console_out ,'r' ) as f :
122127 lines = f .readlines ()
123128 lines [0 ].split ('\n ' )
124129
125- remove_console_output_file ('console.output' )
130+ remove_console_output_file (console_out )
126131
127132 reg_contents = ""
128133 for line in lines :
@@ -151,14 +156,13 @@ def check_device(device, port):
151156 device_value_masked = f'{ device_value_masked :x} '
152157 device_value_masked = device_value_masked .zfill (int (master_data [device ]['IDCHIP' ]['size' ])* 2 )
153158
154- print (f"Device is: { device .split ('-' )[0 ]} " )
159+ print (f"Device is: { device .split ('-' )[0 ]} . " )
155160
156161 #compare with stored master data
157162 if not device_value_masked == master_data [device ]['IDCHIP' ]['value' ]:
158163 raise Exception ("Device connected does not match the selected device to flash" )
159164
160165
161-
162166def check_mem (device , port ):
163167
164168 if "XMC1" in device :
@@ -170,7 +174,7 @@ def check_mem(device, port):
170174 flash_size = (device_value - 1 )* 4 #flash size given by (ADDR-1)*4
171175 flash_size = str (flash_size ).zfill (4 )
172176
173- print (f"Flash size is: { int (flash_size )} kB" )
177+ print (f"Flash size is: { int (flash_size )} kB. " )
174178
175179 # special case for XMC2GO-32kB variant, bypass check
176180 if "XMC1100" in device and int (flash_size ) == 32 :
@@ -194,10 +198,10 @@ def check_mem(device, port):
194198 raise Exception ("Memory size of device connected does not match that of the selected device to flash" )
195199
196200
197- def upload (device , port , binfile ):
201+ def upload (device , port , binfile , enable_jlink_log ):
198202 serial_num = get_device_serial_number (port )
199203 jlink_cmd_file = create_jlink_loadbin_command_file (binfile )
200- jlink_commander (device , serial_num , jlink_cmd_file )
204+ jlink_commander (device , serial_num , jlink_cmd_file , console_output = not enable_jlink_log ) # console_output = true will store the log to file instead of printing
201205 remove_jlink_command_file (jlink_cmd_file )
202206
203207def erase (device , port ):
@@ -217,7 +221,21 @@ def main_parser_func(args):
217221 def parser_upload_func (args ):
218222 check_device (args .device , args .port )
219223 check_mem (args .device , args .port )
220- upload (args .device , args .port , args .binfile )
224+ upload (args .device , args .port , args .binfile , args .verbose )
225+ # remove console output file if verbose is not enabled
226+ if not args .verbose :
227+ # check if upload was successful by parsing the console output
228+ with open (console_out , 'r' ) as f :
229+ found_loadbin = False
230+ for line in f :
231+ if "J-Link>loadbin" in line :
232+ found_loadbin = True
233+ elif found_loadbin and "O.K." in line :
234+ print ("Upload successful." )
235+ break
236+ else :
237+ print ("Upload failed." )
238+ remove_console_output_file (console_out )
221239
222240 def parser_erase_func (args ):
223241 erase (args .device , args .port )
@@ -242,9 +260,10 @@ def __call__(self, parser, namespace, values, option_string, **kwargs):
242260 required_upload .add_argument ('-d' ,'--device' , type = str , help = 'jlink device name' , required = True )
243261 required_upload .add_argument ('-p' ,'--port' , type = str , help = 'serial port' , required = True )
244262 required_upload .add_argument ('-f' ,'--binfile' , type = str , help = 'binary file to upload' , required = True )
263+ required_upload .add_argument ('--verbose' , action = 'store_true' , help = 'Enable verbose logging' )
245264 parser_upload .set_defaults (func = parser_upload_func )
246265
247- # Debug parser
266+ # Erase parser
248267 parser_erase = subparser .add_parser ('erase' , description = 'erase command' )
249268 required_erase = parser_erase .add_argument_group ('required arguments' )
250269 required_erase .add_argument ('-d' ,'--device' , type = str , help = 'jlink device name' , required = True )
@@ -254,8 +273,14 @@ def __call__(self, parser, namespace, values, option_string, **kwargs):
254273 # debug_parser.
255274 # TBD in future
256275
257- # Parser call
276+ # Parse arguments
258277 args = parser .parse_args ()
278+ # Set traceback limit based on the --verbose argument
279+ if args .verbose :
280+ sys .tracebacklimit = None # Enable full traceback
281+ else :
282+ sys .tracebacklimit = 0 # Disable traceback
283+ # Parser call
259284 args .func (args )
260285
261286if __name__ == "__main__" :
0 commit comments