@@ -37,16 +37,17 @@ def set_environment():
3737 elif sys .platform == 'darwin' :
3838 jlinkexe = 'JLinkExe'
3939
40- def discover_devices ():
40+ def discover_jlink_devices ():
4141 ports = comports ()
4242 port_sn_list = []
4343 for p in ports :
44- port_sn_list .append ((p .device , p .serial_number ))
44+ if "JLink" in p .description :
45+ port_sn_list .append ((p .device , p .serial_number ))
4546
4647 return port_sn_list
4748
4849def get_device_serial_number (port ):
49- port_sn_list = discover_devices ()
50+ port_sn_list = discover_jlink_devices ()
5051 for device in port_sn_list :
5152 if device [0 ] == port and device [0 ] != None :
5253 return device [1 ]
@@ -81,6 +82,16 @@ def remove_console_output_file(console_output_file):
8182 if os .path .exists (console_output_file ):
8283 os .remove (console_output_file )
8384
85+ def remove_backspaces (input_str ):
86+ result = []
87+ for char in input_str :
88+ if char == '\b ' :
89+ if result :
90+ result .pop ()
91+ else :
92+ result .append (char )
93+ return '' .join (result )
94+
8495def jlink_commander (device , serial_num , cmd_file , console_output = False ):
8596 jlink_cmd = [jlinkexe , '-autoconnect' , '1' ,'-exitonerror' , '1' , '-nogui' , '1' , '-device' , device , '-selectemubysn' , serial_num , '-if' , 'swd' , '-speed' , '4000' , '-commandfile' , cmd_file ]
8697
@@ -92,10 +103,10 @@ def jlink_commander(device, serial_num, cmd_file, console_output=False):
92103 if console_output is True :
93104 out , err = jlink_proc .communicate ()
94105 with open (console_out , 'w' ) as f :
95- f .write (out )
106+ f .write (remove_backspaces ( out ) )
96107 else :
97108 for line in jlink_proc .stdout :
98- print (line , end = '' )
109+ print (remove_backspaces ( line ) , end = '' )
99110 jlink_proc .wait ()
100111 except :
101112 raise Exception ("jlink error" )
@@ -146,6 +157,12 @@ def get_mem_contents(addr, bytes, device, port):
146157def read_master_data ():
147158 return xmc_master_data
148159
160+ def find_device_by_value (value ):
161+ master_data = read_master_data ()
162+ for device , config in master_data .items ():
163+ if config ["IDCHIP" ]["value" ] == value :
164+ return device
165+ return None
149166
150167def check_device (device , port ):
151168
@@ -156,12 +173,14 @@ def check_device(device, port):
156173 device_value_masked = f'{ device_value_masked :x} '
157174 device_value_masked = device_value_masked .zfill (int (master_data [device ]['IDCHIP' ]['size' ])* 2 )
158175
159- print (f"Device is: { device .split ('-' )[0 ]} ." )
160-
161- #compare with stored master data
162- if not device_value_masked == master_data [device ]['IDCHIP' ]['value' ]:
163- raise Exception ("Device connected does not match the selected device to flash" )
176+ print (f"Selected Device is: { device } ." )
164177
178+ real_device = find_device_by_value (device_value_masked )
179+ #compare with stored master data
180+ if not real_device == device :
181+ if real_device != None :
182+ print (f"Connected Device is: { real_device } ." )
183+ raise Exception (f"Device connected on port { port } does not match the selected device to flash" )
165184
166185def check_mem (device , port ):
167186
@@ -196,7 +215,20 @@ def check_mem(device, port):
196215 #compare with stored master data
197216 if not device_value_masked .upper () == master_data [device ]['FLASH0_ID' ]['value' ]:
198217 raise Exception ("Memory size of device connected does not match that of the selected device to flash" )
199-
218+
219+ def get_default_port (port ):
220+ serial_num = get_device_serial_number (port )
221+ if serial_num == None or port == None :
222+ port_sn_list = discover_jlink_devices ()
223+ for port_sn in port_sn_list :
224+ if port_sn [1 ] != None :
225+ real_port = port_sn [0 ]
226+ print (f"Device found on port: { real_port } , not on the selected port: { port } ." )
227+ print (f"Automatically selecting port { real_port } ..." )
228+ return real_port
229+ else :
230+ return port
231+
200232
201233def upload (device , port , binfile , enable_jlink_log ):
202234 serial_num = get_device_serial_number (port )
@@ -236,6 +268,10 @@ def parser_upload_func(args):
236268 else :
237269 print ("Upload failed." )
238270 remove_console_output_file (console_out )
271+ # Log if the port value has changed
272+ if args .port != original_port :
273+ print (f"Please select port { args .port } for using the Serial Monitor or Plotter." )
274+
239275
240276 def parser_erase_func (args ):
241277 erase (args .device , args .port )
@@ -258,7 +294,7 @@ def __call__(self, parser, namespace, values, option_string, **kwargs):
258294 parser_upload = subparser .add_parser ('upload' , description = 'Upload binary command' )
259295 required_upload = parser_upload .add_argument_group ('required arguments' )
260296 required_upload .add_argument ('-d' ,'--device' , type = str , help = 'jlink device name' , required = True )
261- required_upload .add_argument ('-p' ,'--port' , type = str , help = 'serial port' , required = True )
297+ required_upload .add_argument ('-p' ,'--port' , type = str , nargs = '?' , const = '' , help = 'serial port' )
262298 required_upload .add_argument ('-f' ,'--binfile' , type = str , help = 'binary file to upload' , required = True )
263299 required_upload .add_argument ('--verbose' , action = 'store_true' , help = 'Enable verbose logging' )
264300 parser_upload .set_defaults (func = parser_upload_func )
@@ -280,6 +316,13 @@ def __call__(self, parser, namespace, values, option_string, **kwargs):
280316 sys .tracebacklimit = None # Enable full traceback
281317 else :
282318 sys .tracebacklimit = 0 # Disable traceback
319+
320+ # Store the original port value
321+ original_port = args .port
322+
323+ # Select default port if not provided/ or device not found on the selected port
324+ args .port = get_default_port (args .port )
325+
283326 # Parser call
284327 args .func (args )
285328
0 commit comments