@@ -37,16 +37,17 @@ def set_environment():
37
37
elif sys .platform == 'darwin' :
38
38
jlinkexe = 'JLinkExe'
39
39
40
- def discover_devices ():
40
+ def discover_jlink_devices ():
41
41
ports = comports ()
42
42
port_sn_list = []
43
43
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 ))
45
46
46
47
return port_sn_list
47
48
48
49
def get_device_serial_number (port ):
49
- port_sn_list = discover_devices ()
50
+ port_sn_list = discover_jlink_devices ()
50
51
for device in port_sn_list :
51
52
if device [0 ] == port and device [0 ] != None :
52
53
return device [1 ]
@@ -81,6 +82,16 @@ def remove_console_output_file(console_output_file):
81
82
if os .path .exists (console_output_file ):
82
83
os .remove (console_output_file )
83
84
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
+
84
95
def jlink_commander (device , serial_num , cmd_file , console_output = False ):
85
96
jlink_cmd = [jlinkexe , '-autoconnect' , '1' ,'-exitonerror' , '1' , '-nogui' , '1' , '-device' , device , '-selectemubysn' , serial_num , '-if' , 'swd' , '-speed' , '4000' , '-commandfile' , cmd_file ]
86
97
@@ -92,10 +103,10 @@ def jlink_commander(device, serial_num, cmd_file, console_output=False):
92
103
if console_output is True :
93
104
out , err = jlink_proc .communicate ()
94
105
with open (console_out , 'w' ) as f :
95
- f .write (out )
106
+ f .write (remove_backspaces ( out ) )
96
107
else :
97
108
for line in jlink_proc .stdout :
98
- print (line , end = '' )
109
+ print (remove_backspaces ( line ) , end = '' )
99
110
jlink_proc .wait ()
100
111
except :
101
112
raise Exception ("jlink error" )
@@ -146,6 +157,12 @@ def get_mem_contents(addr, bytes, device, port):
146
157
def read_master_data ():
147
158
return xmc_master_data
148
159
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
149
166
150
167
def check_device (device , port ):
151
168
@@ -156,12 +173,14 @@ def check_device(device, port):
156
173
device_value_masked = f'{ device_value_masked :x} '
157
174
device_value_masked = device_value_masked .zfill (int (master_data [device ]['IDCHIP' ]['size' ])* 2 )
158
175
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 } ." )
164
177
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" )
165
184
166
185
def check_mem (device , port ):
167
186
@@ -196,7 +215,20 @@ def check_mem(device, port):
196
215
#compare with stored master data
197
216
if not device_value_masked .upper () == master_data [device ]['FLASH0_ID' ]['value' ]:
198
217
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
+
200
232
201
233
def upload (device , port , binfile , enable_jlink_log ):
202
234
serial_num = get_device_serial_number (port )
@@ -236,6 +268,10 @@ def parser_upload_func(args):
236
268
else :
237
269
print ("Upload failed." )
238
270
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
+
239
275
240
276
def parser_erase_func (args ):
241
277
erase (args .device , args .port )
@@ -258,7 +294,7 @@ def __call__(self, parser, namespace, values, option_string, **kwargs):
258
294
parser_upload = subparser .add_parser ('upload' , description = 'Upload binary command' )
259
295
required_upload = parser_upload .add_argument_group ('required arguments' )
260
296
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' )
262
298
required_upload .add_argument ('-f' ,'--binfile' , type = str , help = 'binary file to upload' , required = True )
263
299
required_upload .add_argument ('--verbose' , action = 'store_true' , help = 'Enable verbose logging' )
264
300
parser_upload .set_defaults (func = parser_upload_func )
@@ -280,6 +316,13 @@ def __call__(self, parser, namespace, values, option_string, **kwargs):
280
316
sys .tracebacklimit = None # Enable full traceback
281
317
else :
282
318
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
+
283
326
# Parser call
284
327
args .func (args )
285
328
0 commit comments