1- import argparse , subprocess , os , sys , re , warnings , tempfile
1+ import argparse , subprocess , os , sys , re , tempfile , logging
22from serial .tools .list_ports import comports
33from xmc_data import xmc_master_data
44
@@ -43,7 +43,7 @@ def discover_jlink_devices():
4343 jlink_pattern = r'[Jj][-\s]?[Ll][Ii][Nn][Kk]'
4444 for p in ports :
4545 if re .search (jlink_pattern , p .description ):
46- port_sn_list .append ((p .device , p .serial_number ))
46+ port_sn_list .append ((p .device , p .serial_number , p . description ))
4747
4848 return port_sn_list
4949
@@ -136,28 +136,23 @@ def get_mem_contents(addr, bytes, device, port, enable_update):
136136 serial_num = get_device_serial_number (port )
137137 check_serial_number (serial_num )
138138 except ValueError as e :
139- print (e )
139+ logging . error (e )
140140 jlink_cmd_file = create_jlink_mem_read_command_file (addr , bytes , enable_update ) # todo: comes from proper metafile
141141 jlink_commander (device , serial_num , jlink_cmd_file , True )
142142 remove_jlink_command_file (jlink_cmd_file )
143-
144143 with open (console_out ,'r' ) as f :
145144 lines = f .readlines ()
146145 lines [0 ].split ('\n ' )
147-
148146 remove_console_output_file (console_out )
149-
150147 reg_contents = ""
151148 for line in lines :
152- if getattr (sys , 'verbose' , True ):
153- print (f"JLink Log: { line } " )
149+ logging .debug (f"JLink Log: { line .strip ()} " )
154150 if addr in line and '=' in line :
155151 reg_contents = re .findall ('[0-9,A-F]+' , line )
156152 break
157-
158153 if not reg_contents :
154+ logging .error (f"Wrong COM Port selected! { port } " )
159155 raise Exception (f"Wrong COM Port selected! { port } \n " )
160-
161156 reg_contents .remove (addr ) # remove the addr from the list, just keep reg contents
162157 reg_contents .reverse () # jlink returns LSB first, so reverse it to get MSB on the left side
163158 reg_contents = '' .join (reg_contents )
@@ -174,25 +169,22 @@ def find_device_by_value(value):
174169 return None
175170
176171def check_device (device , port , enable_update ):
177-
178172 master_data = read_master_data ()
179173 # get value from reg
180174 device_value = get_mem_contents (master_data [device ]['IDCHIP' ]['addr' ], master_data [device ]['IDCHIP' ]['size' ], device , port , enable_update )
181175 device_value_masked = (int ('0x' + device_value ,16 )) & (int ('0x' + master_data [device ]['IDCHIP' ]['mask' ],16 )) # take only those bits which are needed
182176 device_value_masked = f'{ device_value_masked :x} '
183177 device_value_masked = device_value_masked .zfill (int (master_data [device ]['IDCHIP' ]['size' ])* 2 )
184-
185- print (f"Selected Device is: { device } ." )
186-
178+ logging .info (f"Selected Device is: { device } ." )
187179 real_device = find_device_by_value (device_value_masked )
188180 #compare with stored master data
189181 if not real_device == device :
190182 if real_device != None :
191- print (f"Connected Device is: { real_device } ." )
192- raise Exception (f"Device connected on port { port } does not match the selected device to flash" )
183+ logging .info (f"Connected Device is: { real_device } ." )
184+ logging .error (f"Device connected on port { port } does not match the selected device { device } ." )
185+ raise Exception ("Device connection mismatch." )
193186
194187def check_mem (device , port , enable_update ):
195-
196188 if "XMC1" in device :
197189 master_data = read_master_data ()
198190 # get value from reg
@@ -201,44 +193,39 @@ def check_mem(device, port, enable_update):
201193 device_value = device_value >> int (master_data [device ]['FLSIZE' ]['bitposition_LSB' ])
202194 flash_size = (device_value - 1 )* 4 #flash size given by (ADDR-1)*4
203195 flash_size = str (flash_size ).zfill (4 )
204-
205- print (f"Flash size is: { int (flash_size )} kB." )
206-
196+ logging .info (f"Flash size is: { int (flash_size )} kB." )
207197 # special case for XMC2GO-32kB variant, bypass check
208198 if "XMC1100" in device and int (flash_size ) == 32 :
209- warnings . warn ("XMC2GO 32kB varaint detected!" )
199+ logging . warning ("XMC2GO 32kB varaint detected!" )
210200 return
211-
212201 #compare with selected device
213202 if not flash_size == device .split ('-' )[1 ]:
214- raise Exception ( "Memory size of device connected does not match that of the selected device to flash" )
215-
203+ logging . error ( f "Memory size of device connected { flash_size } does not match that of the selected device to flash: { device . split ( '-' )[ 1 ] } " )
204+ raise Exception ( "Memory size mismatch." )
216205 else : #XMC4 series
217206 master_data = read_master_data ()
218207 # get value from reg
219208 device_value = get_mem_contents (master_data [device ]['FLASH0_ID' ]['addr' ], master_data [device ]['FLASH0_ID' ]['size' ], device , port , enable_update )
220209 device_value_masked = (int ('0x' + device_value ,16 )) & (int ('0x' + master_data [device ]['FLASH0_ID' ]['mask' ],16 )) # take only those bits which are needed
221210 device_value_masked = f'{ device_value_masked :x} '
222211 device_value_masked = device_value_masked .zfill (int (master_data [device ]['FLASH0_ID' ]['size' ])* 2 )
223-
224212 #compare with stored master data
225213 if not device_value_masked .upper () == master_data [device ]['FLASH0_ID' ]['value' ]:
226- raise Exception ("Memory size of device connected does not match that of the selected device to flash" )
214+ logging .error (f"Memory size of device connected { flash_size } does not match that of the selected device to flash: { device .split ('-' )[1 ]} " )
215+ raise Exception ("Memory size mismatch." )
227216
228- def get_default_port (port ):
217+ def check_port (port ):
229218 serial_num = get_device_serial_number (port )
230219 if serial_num == None or port == None :
231220 port_sn_list = discover_jlink_devices ()
232221 for port_sn in port_sn_list :
233222 if port_sn [1 ] != None :
234223 real_port = port_sn [0 ]
235- print (f"Device found on port: { real_port } , not on the selected port: { port } ." )
236- print (f"Automatically selecting port { real_port } ..." )
237- return real_port
224+ logging .error (f"Device found:{ port_sn_list } . You select { port } . Please select the correct port." )
225+ raise Exception ("Wrong COM Port selected." )
238226 else :
239- return port
227+ return
240228
241-
242229def upload (device , port , binfile , enable_jlink_log , enable_update ):
243230 serial_num = get_device_serial_number (port )
244231 jlink_cmd_file = create_jlink_loadbin_command_file (binfile , enable_update )
@@ -254,44 +241,51 @@ def erase(device, port, enable_update):
254241def debug (device , port , elfile ):
255242 pass #TBD
256243
244+ def setup_logger (verbose = False ):
245+ if verbose :
246+ level = logging .DEBUG
247+ else :
248+ level = logging .INFO
249+ logging .basicConfig (
250+ level = level ,
251+ format = "%(asctime)s [%(levelname)s] %(message)s" ,
252+ datefmt = "%H:%M:%S"
253+ )
254+
257255def parser ():
258256
259257 def main_parser_func (args ):
260258 parser .print_help ()
261259
262260 def parser_upload_func (args ):
263- check_device (args .device , args .port , args .jlink_update )
264- check_mem (args .device , args .port , args .jlink_update )
265- upload (args .device , args .port , args .binfile , args .verbose , args .jlink_update )
266- # remove console output file if verbose is not enabled
261+
262+ check_port (args .port )
263+ check_device (args .device , args .port , args .fw_jlink_update )
264+ check_mem (args .device , args .port , args .fw_jlink_update )
265+ upload (args .device , args .port , args .binfile , args .verbose , args .fw_jlink_update )
267266 if not args .verbose :
268- # check if upload was successful by parsing the console output
269267 with open (console_out , 'r' ) as f :
270268 found_loadbin = False
271269 for line in f :
272270 if "J-Link>loadbin" in line :
273271 found_loadbin = True
274272 elif found_loadbin and "O.K." in line :
275- print ("Upload successful." )
273+ logging . info ("Upload successful." )
276274 break
277275 else :
278- print ("Upload failed." )
276+ logging . error ("Upload failed." )
279277 remove_console_output_file (console_out )
280-
281- # Log if the port value has changed
282- if args .port != original_port :
283- print (f"Please select port { args .port } for using the Serial Monitor or Plotter." )
284278
285279
286280 def parser_erase_func (args ):
287- erase (args .device , args .port , args .jlink_update )
281+ erase (args .device , args .port , args .fw_jlink_update )
288282
289283 class ver_action (argparse .Action ):
290284 def __init__ (self , option_strings , dest , ** kwargs ):
291285 return super ().__init__ (option_strings , dest , nargs = 0 , default = argparse .SUPPRESS , ** kwargs )
292286
293287 def __call__ (self , parser , namespace , values , option_string , ** kwargs ):
294- print ('xmc-flasher version: ' + version )
288+ logging . info ('xmc-flasher version: ' + version )
295289 parser .exit ()
296290
297291 # General parser
@@ -307,36 +301,32 @@ def __call__(self, parser, namespace, values, option_string, **kwargs):
307301 required_upload .add_argument ('-p' ,'--port' , type = str , nargs = '?' , const = '' , help = 'serial port' )
308302 required_upload .add_argument ('-f' ,'--binfile' , type = str , help = 'binary file to upload' , required = True )
309303 required_upload .add_argument ('--verbose' , action = 'store_true' , help = 'Enable verbose logging' )
310- parser_upload .add_argument ('--no-jlink -update' , dest = 'jlink_update ' , action = 'store_false' , help = 'Disable JLink firmware update (default: enabled)' )
311- parser_upload .set_defaults (jlink_update = True )
304+ parser_upload .add_argument ('--no-fw -update' , dest = 'fw_jlink_update ' , action = 'store_false' , help = 'Disable JLink firmware update (default: enabled)' )
305+ parser_upload .set_defaults (fw_jlink_update = True )
312306 parser_upload .set_defaults (func = parser_upload_func )
313307
314308 # Erase parser
315309 parser_erase = subparser .add_parser ('erase' , description = 'erase command' )
316310 required_erase = parser_erase .add_argument_group ('required arguments' )
317311 required_erase .add_argument ('-d' ,'--device' , type = str , help = 'jlink device name' , required = True )
318312 required_erase .add_argument ('-p' ,'--port' , type = str , help = 'serial port' , required = True )
319- parser_erase .add_argument ('--no-jlink -update' , dest = 'jlink_update ' , action = 'store_false' , help = 'Disable JLink firmware update (default: enabled)' )
320- parser_erase .set_defaults (jlink_update = True )
313+ parser_erase .add_argument ('--no-fw -update' , dest = 'fw_jlink_update ' , action = 'store_false' , help = 'Disable JLink firmware update (default: enabled)' )
314+ parser_erase .set_defaults (fw_jlink_update = True )
321315 parser_erase .set_defaults (func = parser_erase_func )
322316
323317 # debug_parser.
324318 # TBD in future
325319
326320 # Parse arguments
327321 args = parser .parse_args ()
328- # Set traceback limit based on the --verbose argument
322+
323+ # Logging option
324+ setup_logger (verbose = args .verbose )
329325 if args .verbose :
330326 sys .tracebacklimit = None # Enable full traceback
331327 else :
332328 sys .tracebacklimit = 0 # Disable traceback
333329
334- # Store the original port value
335- original_port = args .port
336-
337- # Select default port if not provided/ or device not found on the selected port
338- args .port = get_default_port (args .port )
339-
340330 # Parser call
341331 args .func (args )
342332
0 commit comments