programmer-core 1.0.29__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,775 @@
1
+ import os
2
+ from os.path import basename, isfile
3
+ import json
4
+ import pathlib
5
+ import logging
6
+ import time
7
+
8
+ from communicator_core import (
9
+ BinaryDownloader,
10
+ DeviceLifeCycleNum,
11
+ DSSMStatus,
12
+ CC35XX,
13
+ CC35XXE,
14
+ CC37XXR,
15
+ )
16
+ from flash_images_builder_core import (
17
+ FlashImage,
18
+ ProgInstImgBuilder,
19
+ BootSectorFromImgBuilder,
20
+ ActionReqBuilder,
21
+ FIBUtility,
22
+ GPE_MANIFEST_INTEGRITY_SIZE
23
+ )
24
+
25
+ try:
26
+ from report import (
27
+ ProgrammingReportGeneratorCC35XXE,
28
+ ProgrammingReportGeneratorCC35XX,
29
+ )
30
+ from constants import FLASH_STATUS, FLASH_IMAGE_HEADER, WAIT_FOR_ERASE
31
+ from utility import (
32
+ ProgrammerUtility,
33
+ get_lifecycle_state_reg_class,
34
+ )
35
+ except ImportError:
36
+ from .report import (
37
+ ProgrammingReportGeneratorCC35XXE,
38
+ ProgrammingReportGeneratorCC35XX,
39
+ )
40
+ from .constants import FLASH_STATUS, FLASH_IMAGE_HEADER, WAIT_FOR_ERASE
41
+ from .utility import (
42
+ ProgrammerUtility,
43
+ get_lifecycle_state_reg_class,
44
+ )
45
+
46
+ # uncomment for debug communicator code without build package communicator_core for every change
47
+ # if 'communicator' in sys.modules.keys():
48
+ # from communicator.communicator_core.core.cc35xx_config_ap import DeviceLifeCycleNum, DSSMStatus, LifeCycleStateReg
49
+ # from communicator.communicator_core.core.binary_downloader import BinaryDownloader
50
+
51
+
52
+ PROGRAMMER_PROGRAM_LOGGER = logging.getLogger("program")
53
+
54
+
55
+ # note: 0x4110295c - hw life cycle address
56
+ class ProgramDevice:
57
+ SIMULATION = "DEMO"
58
+
59
+ FLASH_IMAGE_TYPE_CC35XX = {
60
+ "boot_sector": "boot_sector_logical",
61
+ "primary_tbl": "ti_bl_slot1_logical",
62
+ "secondary_tbl": "ti_bl_slot2_logical",
63
+ "primary_vendor_sbl": "vendor_sbl_slot1_logical",
64
+ "secondary_vendor_sbl": "vendor_sbl_slot2_logical",
65
+ "primary_vendor_image": "vendor_img_slot1_logical",
66
+ "secondary_vendor_image": "vendor_img_slot2_logical",
67
+ "primary_ti_wsoc": "ti_wsoc_img_slot1_logical",
68
+ "secondary_ti_wsoc": "ti_wsoc_img_slot2_logical",
69
+ }
70
+ FLASH_IMAGE_TYPE_CC35XXE = {
71
+ "boot_sector": "boot_sector_logical",
72
+ "primary_tbl": "ti_bl_slot1_logical",
73
+ "secondary_tbl": "ti_bl_slot2_logical",
74
+ "primary_vendor_sbl": "vendor_sbl_slot1_logical",
75
+ "secondary_vendor_sbl": "vendor_sbl_slot2_logical",
76
+ "primary_vendor_image": "vendor_img_slot1_logical",
77
+ "secondary_vendor_image": "vendor_img_slot2_logical",
78
+ "primary_ti_wsoc": "ti_wsoc_img_slot1_logical",
79
+ "secondary_ti_wsoc": "ti_wsoc_img_slot2_logical",
80
+ "primary_ti_wsoc_bl2": "ti_wsoc_bl2_img_slot1_logical",
81
+ "secondary_ti_wsoc_bl2": "ti_wsoc_bl2_img_slot2_logical",
82
+ "protected_storage": "nvs_slot_logical",
83
+ }
84
+ # Dictionary to map device types to their corresponding flash image types
85
+ # TODO: temporary - using CC35XXE FLASH_IMAGE_TYPES until CC37XXR FLASH_IMAGE_TYPES are available
86
+ FLASH_IMAGE_TYPES = {
87
+ CC35XXE: FLASH_IMAGE_TYPE_CC35XXE,
88
+ CC35XX: FLASH_IMAGE_TYPE_CC35XX,
89
+ CC37XXR: FLASH_IMAGE_TYPE_CC35XXE,
90
+ }
91
+ SMART_ERASE_FILE_SIZE_THOLD = 750e3
92
+
93
+ def __init__(
94
+ self,
95
+ interface_type,
96
+ serial_number,
97
+ tool_settings,
98
+ programmer_artifacts_path,
99
+ fib_artifacts_path,
100
+ device_type,
101
+ report_file_path=None,
102
+ reset_on_timeout=True,
103
+ wait_timeout=40,
104
+ wait_for_erase=None,
105
+ write_timeout=0,
106
+ tclk_delay=4,
107
+ chunk_size=1085,
108
+ verbose=False,
109
+ update_progress=None,
110
+ push_message=None,
111
+ jlink_speed_khz=None,
112
+ ):
113
+ self.tool_settings = tool_settings
114
+ self.prog_inst_image_path = None
115
+ self.programming_action_req_path = None
116
+ self.flash_images_list = []
117
+ self.path_to_ti_programmer = None
118
+ self.prog_utility = ProgrammerUtility(
119
+ programmer_artifacts_path, fib_artifacts_path
120
+ )
121
+ self.fib_utility = FIBUtility(
122
+ fib_artifacts_path=fib_artifacts_path
123
+ )
124
+
125
+ self.report_file_path = (
126
+ report_file_path
127
+ if report_file_path
128
+ else (pathlib.Path(self.tool_settings).parent / "programming_report.txt")
129
+ )
130
+ self.reset_on_timeout = reset_on_timeout
131
+
132
+ self.interface_type = interface_type
133
+ self.serial_number = serial_number
134
+ self.wait_timeout = wait_timeout
135
+ self.write_timeout = write_timeout
136
+ self.erase_wait_timeout = (
137
+ WAIT_FOR_ERASE if wait_for_erase is None else wait_for_erase
138
+ )
139
+ self.vendor_ask_for_update_fuse = False
140
+ self.full_flash_erase = False
141
+
142
+ # just for download flash images - Step 5
143
+ self.tclk_delay = tclk_delay
144
+ self.chunk_size = chunk_size
145
+ self.jlink_speed_khz = jlink_speed_khz
146
+
147
+ self.verbose = verbose
148
+ self.log_level = logging.INFO if verbose else logging.DEBUG
149
+
150
+ self.error_message = ""
151
+ self.rollback_mismatches = []
152
+ self.device_type = device_type
153
+
154
+ # Initialize the appropriate LifeCycleStateReg class based on device type
155
+ self._lifecycle_reg_class = get_lifecycle_state_reg_class(self.device_type)
156
+
157
+ # TODO: temporary - CC37XXR uses CC35XXE report generator until CC37XXR specific generators are available
158
+ if self.device_type in [CC35XXE, CC37XXR]:
159
+ self.report_generator = ProgrammingReportGeneratorCC35XXE(
160
+ programmer_artifacts_path=programmer_artifacts_path,
161
+ fib_artifacts_path=fib_artifacts_path,
162
+ report_file_path=self.report_file_path,
163
+ verbose=self.verbose,
164
+ )
165
+ else:
166
+ self.report_generator = ProgrammingReportGeneratorCC35XX(
167
+ programmer_artifacts_path=programmer_artifacts_path,
168
+ fib_artifacts_path=fib_artifacts_path,
169
+ report_file_path=self.report_file_path,
170
+ verbose=self.verbose,
171
+ )
172
+
173
+ self.path_to_ti_bootloader = self.prog_utility.get_default_tbl_img(
174
+ self.device_type
175
+ )
176
+
177
+ self.path_to_ti_programmer = self.prog_utility.get_default_prog(
178
+ self.device_type
179
+ )
180
+
181
+ # For Uniflash Support
182
+ self.update_progress = update_progress
183
+ self.push_message = push_message
184
+
185
+ def _create_boot_sector(self):
186
+ abs_dir_out_path = pathlib.Path(self.tool_settings).parent
187
+ # TODO: get the version from prog_inst_image
188
+ boot_sector_builder = BootSectorFromImgBuilder(
189
+ image_file_path=self.prog_inst_image_path,
190
+ abs_dir_out_path=abs_dir_out_path,
191
+ version="0.0.1.0",
192
+ device=self.device_type,
193
+ verbose=self.verbose,
194
+ )
195
+ boot_sector_builder.build()
196
+
197
+ return boot_sector_builder.boot_sector_image_out_path
198
+
199
+ def _get_selected_images(self, prog_action_req_path):
200
+
201
+ with open(prog_action_req_path, "rb") as f:
202
+ action_req_content_row = f.read()
203
+
204
+ action_req_builder = ActionReqBuilder(
205
+ header_version=None,
206
+ type=ActionReqBuilder.PROGRAMMING,
207
+ device_type=self.device_type,
208
+ payload_param=None,
209
+ )
210
+
211
+ action_req_parsed = action_req_builder.parse(action_req_content_row)
212
+
213
+ # TODO: check if this field exist or catch an error if false
214
+ selected_images = action_req_parsed["payload"]["action_payload"][
215
+ "prog_req_content"
216
+ ]
217
+
218
+ return selected_images
219
+
220
+ def _get_flash_images(self, json_cont):
221
+ flash_images_list = []
222
+ vendor_images = [] # Store vendor_images to append after all non-vendor images
223
+ vendor_bl3_images = [] # Store vendor_bl3 images to append after vendor_images
224
+ # TODO: for future get_flash_map_entity is part of boot_sector_generation
225
+ prog_inst_flash_map = ProgInstImgBuilder.get_flash_map_entity(
226
+ self.prog_inst_image_path, self.device_type
227
+ )
228
+
229
+ selected_images = self._get_selected_images(self.programming_action_req_path)
230
+ for image_type in selected_images:
231
+ # check if user want to download the image
232
+ # TODO: change bitinteger(1) to Flag in FIB in order to get true/false as a return value
233
+ if selected_images[image_type] == 1:
234
+ # Check if the image can be a flash image
235
+ if (
236
+ self.device_type in self.FLASH_IMAGE_TYPES
237
+ and image_type
238
+ not in self.FLASH_IMAGE_TYPES[self.device_type].keys()
239
+ ):
240
+ # Check if the user asks for fuse update
241
+ if image_type == "fuse_programming_instruction_update":
242
+ self.vendor_ask_for_update_fuse = True
243
+ elif image_type == "flash_factory_reset":
244
+ self.full_flash_erase = True
245
+ continue
246
+
247
+ if image_type == "boot_sector":
248
+ # check if the user didnt gave path
249
+ if json_cont[image_type] is None or json_cont[image_type] == "":
250
+ # create boot sector
251
+ image_path = self.prog_utility.build_boot_sector(
252
+ programming_sign_image_path=self.prog_inst_image_path,
253
+ dir_out_path=pathlib.Path(self.prog_inst_image_path).parent,
254
+ device_type=self.device_type,
255
+ )
256
+ else:
257
+ image_path = json_cont[image_type]
258
+
259
+ elif image_type == "primary_tbl":
260
+ # creating primary_tbl if he is in action req and not in tool_settings.json
261
+ if json_cont[image_type] is None or json_cont[image_type] == "":
262
+ image_path = self.prog_utility.build_tbl_image(
263
+ ti_sign_container=self.path_to_ti_bootloader,
264
+ dir_out_path=pathlib.Path(self.prog_inst_image_path).parent,
265
+ device=self.device_type,
266
+ )
267
+ else:
268
+ image_path = json_cont[image_type]
269
+ else:
270
+ image_path = json_cont[image_type]
271
+
272
+ if image_path in [None, ""]:
273
+ self.error_message = f'Path to "{image_type}" is invalid or not provided in tool_settings.json'
274
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
275
+ return []
276
+
277
+ image_path = self.prog_utility.fix_path(image_path)
278
+ # check image path validation
279
+ res = self.prog_utility.file_path_exist(image_path, image_type)
280
+ if res is not None:
281
+ self.error_message = res
282
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
283
+ return []
284
+
285
+ # get flash_map_img_index by the location in FLASH_IMAGE_TYPE
286
+ image_address = hex(
287
+ prog_inst_flash_map[
288
+ self.FLASH_IMAGE_TYPES[self.device_type][image_type]
289
+ ]
290
+ )
291
+
292
+ # minus 16 bytes if the device is cc35xxe
293
+ if (self.device_type in [CC35XXE, CC37XXR]) and image_type not in [
294
+ "boot_sector",
295
+ "protected_storage",
296
+ ]:
297
+ image_address = hex(
298
+ int(image_address, 16) - GPE_MANIFEST_INTEGRITY_SIZE
299
+ )
300
+
301
+ # wrap flash image file with address-len-paddinglen with FIB function
302
+ flash_img_builder = FlashImage(
303
+ image_path=image_path, address=image_address, verbose=self.verbose
304
+ )
305
+ flash_img_builder.build()
306
+
307
+ # save flash_image
308
+ flash_image_name = (
309
+ basename(image_path).split(".")[0] + ".flashready.bin"
310
+ )
311
+ flash_image_path = pathlib.Path(image_path).parent / flash_image_name
312
+ with open(flash_image_path, "wb") as f:
313
+ f.write(flash_img_builder.flash_image_content_raw)
314
+ PROGRAMMER_PROGRAM_LOGGER.log(
315
+ self.log_level, f"Saved flash image bin file at {flash_image_path}"
316
+ )
317
+
318
+ # add image to list
319
+ if image_type == "boot_sector":
320
+ flash_images_list.insert(0, flash_image_path)
321
+ elif image_type in ("primary_vendor_image", "secondary_vendor_image"):
322
+ vendor_images.append(flash_image_path)
323
+ elif image_type in ("primary_vendor_sbl", "secondary_vendor_sbl"):
324
+ vendor_bl3_images.append(flash_image_path)
325
+ else:
326
+ flash_images_list.append(flash_image_path)
327
+
328
+ # Append vendor_images, then vendor_bl3 images at the end
329
+ flash_images_list.extend(vendor_images)
330
+ flash_images_list.extend(vendor_bl3_images)
331
+
332
+ return flash_images_list
333
+
334
+ def _delete_flash_images(self):
335
+ for flash_image in self.flash_images_list:
336
+ if os.path.exists(flash_image):
337
+ os.remove(flash_image)
338
+
339
+ # For Uniflash Support
340
+ def _uniflash_update_progress(self, message, progress, error=False):
341
+ if self.update_progress and self.push_message:
342
+ self.update_progress(message, progress)
343
+ self.push_message(message, 0 if not error else 2)
344
+
345
+ def program(self):
346
+
347
+ # pull out images path from json
348
+ with open(self.prog_utility.fix_path(self.tool_settings), "r") as f:
349
+ tool_settings_cont = json.load(f)
350
+
351
+ programming_components = tool_settings_cont[
352
+ "programming_debug_and_ota_signed_components"
353
+ ]
354
+
355
+ # define programming tbl path
356
+ if programming_components["tbl_container_programming"] is not None:
357
+ self.path_to_ti_programmer = programming_components[
358
+ "tbl_container_programming"
359
+ ]
360
+
361
+ self.path_to_ti_programmer = self.prog_utility.fix_path(
362
+ self.path_to_ti_programmer
363
+ )
364
+ res = self.prog_utility.file_path_exist(
365
+ self.path_to_ti_programmer, "tbl_container_programming"
366
+ )
367
+ if res is not None:
368
+ self.error_message = res
369
+ self._uniflash_update_progress(self.error_message, 0, True)
370
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
371
+ return False
372
+
373
+ # check if required path exist
374
+ if programming_components["programming_instructions"] in [None, ""]:
375
+ self.error_message = (
376
+ 'Path to "programming_instructions" is required in tool_settings.json'
377
+ )
378
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
379
+ return False
380
+
381
+ self.prog_inst_image_path = self.prog_utility.fix_path(
382
+ programming_components["programming_instructions"]
383
+ )
384
+ res = self.prog_utility.file_path_exist(
385
+ self.prog_inst_image_path, "programming_instructions"
386
+ )
387
+ if res is not None:
388
+ self.error_message = res
389
+ self._uniflash_update_progress(self.error_message, 0, True)
390
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
391
+ return False
392
+
393
+ if programming_components["actions_req_paths"]["programming"] in [None, ""]:
394
+ self.error_message = 'Path to "programming" in "actions_req_paths" is required in tool_settings.json'
395
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
396
+ return False
397
+
398
+ self.programming_action_req_path = self.prog_utility.fix_path(
399
+ programming_components["actions_req_paths"]["programming"]
400
+ )
401
+ res = self.prog_utility.file_path_exist(
402
+ self.programming_action_req_path, "programming_actions_req"
403
+ )
404
+ if res is not None:
405
+ self.error_message = res
406
+ self._uniflash_update_progress(self.error_message, 0, True)
407
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
408
+ return False
409
+
410
+ self.flash_images_list = self._get_flash_images(programming_components)
411
+
412
+ # check if at least one request inside action req is on
413
+ # if (
414
+ # self.flash_images_list == []
415
+ # and not self.vendor_ask_for_update_fuse
416
+ # and not self.full_flash_erase
417
+ # ):
418
+ # if self.error_message == "":
419
+ # self.error_message = "Action Request does not contain any programming request content. Please fix it and try again."
420
+ # self._uniflash_update_progress(self.error_message, 0, True)
421
+ # PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
422
+ # return False
423
+
424
+ #################################################
425
+ ## Step 1 ##
426
+ ## Reset device and download TI Programmer ##
427
+ #################################################
428
+ self._uniflash_update_progress("Reset device and download TI Programmer", 20)
429
+
430
+ ti_programmer_download = BinaryDownloader(
431
+ bin_file=self.path_to_ti_programmer,
432
+ interface_type=self.interface_type,
433
+ serial_number=self.serial_number,
434
+ wait_timeout=self.wait_timeout,
435
+ write_timeout=self.write_timeout,
436
+ verbose=self.verbose,
437
+ tclk_delay=self.tclk_delay,
438
+ chunk_size=self.chunk_size,
439
+ jlink_speed_khz=self.jlink_speed_khz,
440
+ )
441
+
442
+ # reset device
443
+ ti_programmer_download.device.reset_device()
444
+
445
+ # Download TI bootloader
446
+ ti_programmer_download.daemon = True
447
+ ti_programmer_download.start()
448
+
449
+ while ti_programmer_download.is_alive():
450
+ ti_programmer_download.join(0.1)
451
+
452
+ error_code, error_msg = ti_programmer_download.download_status
453
+
454
+ if error_code > 0:
455
+ PROGRAMMER_PROGRAM_LOGGER.log(self.log_level, "Successfully loaded binary")
456
+ else:
457
+ self.error_message = f"Failed loading 'TI Programmer' image"
458
+ self._uniflash_update_progress(self.error_message, 0, True)
459
+ PROGRAMMER_PROGRAM_LOGGER.error(
460
+ f"Failed loading binary with error code: {error_code}\nError message: {error_msg}"
461
+ )
462
+ return False
463
+
464
+ #################################################
465
+ ## Step 2 ##
466
+ ## Read CFGAP and check life-cycle/dssm status ##
467
+ #################################################
468
+ self._uniflash_update_progress(
469
+ "Read CFGAP and check life-cycle/dssm status", 25
470
+ )
471
+
472
+ if self.interface_type != self.SIMULATION:
473
+ # Read cfgap - use device-specific register class
474
+ life_cycle_state_reg = self._lifecycle_reg_class(
475
+ interface=self.interface_type,
476
+ serial_number=self.serial_number,
477
+ verbose=self.verbose,
478
+ )
479
+ life_cycle_state_reg.read_reg()
480
+ life_cycle = life_cycle_state_reg.life_cycle_sw_coded
481
+ dssm_status = life_cycle_state_reg.dssm_status
482
+ life_cycle_state_reg.disconnect()
483
+
484
+ # Check if life cycle is one of allowed_life_cycle
485
+ allowed_life_cycle = [
486
+ DeviceLifeCycleNum.DEPLOYED,
487
+ DeviceLifeCycleNum.RMA_HW_ANALYSIS,
488
+ DeviceLifeCycleNum.RMA_FAILIURE_ANALYSIS,
489
+ ]
490
+ if life_cycle not in allowed_life_cycle:
491
+ self.error_message = "Life cycle is not valid"
492
+ self._uniflash_update_progress(self.error_message, 0, True)
493
+ PROGRAMMER_PROGRAM_LOGGER.error(
494
+ f"Process is stopped. Life cycle {DeviceLifeCycleNum(life_cycle).name} is not valid."
495
+ )
496
+ return False
497
+
498
+ # Check if dssm status is DSSM_READY
499
+ if not dssm_status == DSSMStatus.DSSM_READY:
500
+ self.error_message = f"Device is not ready for programming"
501
+ self._uniflash_update_progress(self.error_message, 0, True)
502
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
503
+ return False
504
+
505
+ #################################################
506
+ ## Step 3 ##
507
+ ## Download programming action request ##
508
+ #################################################
509
+ self._uniflash_update_progress("Download programming action request", 30)
510
+
511
+ programming_req_download = BinaryDownloader(
512
+ bin_file=self.programming_action_req_path,
513
+ interface_type=self.interface_type,
514
+ serial_number=self.serial_number,
515
+ wait_timeout=self.wait_timeout,
516
+ write_timeout=self.write_timeout,
517
+ verbose=self.verbose,
518
+ tclk_delay=self.tclk_delay,
519
+ chunk_size=self.chunk_size,
520
+ jlink_speed_khz=self.jlink_speed_khz,
521
+ )
522
+
523
+ programming_req_download.daemon = True
524
+ programming_req_download.start()
525
+
526
+ while programming_req_download.is_alive():
527
+ programming_req_download.join(0.1)
528
+
529
+ error_code, error_msg = programming_req_download.download_status
530
+
531
+ if error_code > 0:
532
+ PROGRAMMER_PROGRAM_LOGGER.log(self.log_level, "Successfully loaded binary")
533
+ else:
534
+ self.error_message = f"Failed loading 'Programming Action Request'"
535
+ self._uniflash_update_progress(self.error_message, 0, True)
536
+ PROGRAMMER_PROGRAM_LOGGER.error(
537
+ f"Failed loading binary with error code: {error_code}\nError message: {error_msg}"
538
+ )
539
+ return False
540
+
541
+ #################################################
542
+ ## Step 4 ##
543
+ ## Download programming instructions image ##
544
+ #################################################
545
+ self._uniflash_update_progress("Download programming instructions image", 35)
546
+
547
+ wait_for_resp = True if len(self.flash_images_list) == 0 else False
548
+
549
+ prog_inst_downloader = BinaryDownloader(
550
+ bin_file=self.prog_inst_image_path,
551
+ interface_type=self.interface_type,
552
+ serial_number=self.serial_number,
553
+ wait_timeout=self.wait_timeout,
554
+ write_timeout=self.write_timeout,
555
+ wait_for_resp=wait_for_resp,
556
+ verbose=self.verbose,
557
+ tclk_delay=self.tclk_delay,
558
+ chunk_size=self.chunk_size,
559
+ expected_resp_size=self.report_generator.get_report_struct_size(),
560
+ jlink_speed_khz=self.jlink_speed_khz,
561
+ )
562
+ prog_inst_downloader.daemon = True
563
+ prog_inst_downloader.start()
564
+
565
+ while prog_inst_downloader.is_alive():
566
+ prog_inst_downloader.join(0.1)
567
+
568
+ error_code, error_msg = prog_inst_downloader.download_status
569
+
570
+ if error_code > 0:
571
+ PROGRAMMER_PROGRAM_LOGGER.log(self.log_level, "Successfully loaded binary")
572
+ else:
573
+ self.error_message = "Failed loading 'Programming Instruction' image"
574
+ self._uniflash_update_progress(self.error_message, 0, True)
575
+ PROGRAMMER_PROGRAM_LOGGER.error(
576
+ f"Failed loading binary with error code: {error_code}\nError message: {error_msg}"
577
+ )
578
+ return False
579
+
580
+ #################################################
581
+ ## Step 5 ##
582
+ ## Download flash images ##
583
+ #################################################
584
+ total_flash_images = len(self.flash_images_list)
585
+ start_percent = 35 # already shown before the loop
586
+ end_percent = 90 # where we want to finish
587
+
588
+ for idx, flash_image in enumerate(self.flash_images_list):
589
+ cur_percent = int(
590
+ start_percent
591
+ + (idx + 1) / total_flash_images * (end_percent - start_percent)
592
+ )
593
+ self._uniflash_update_progress(
594
+ f"Downloading {basename(flash_image)} ...", cur_percent
595
+ )
596
+
597
+ for flash_image in self.flash_images_list:
598
+ # if image is last element --> wait_for_resp depend on the user input
599
+ wait_for_resp = flash_image == self.flash_images_list[-1]
600
+
601
+ # split file image to 2 files - one with the header and other with the rest of the image. then create 2 binarydownloader
602
+ file_name = flash_image.stem
603
+ file_name_header = "header_" + file_name + ".bin"
604
+ file_name_content = "content_" + file_name + ".bin"
605
+ image_header_path = flash_image.parent / file_name_header
606
+ image_content_path = flash_image.parent / file_name_content
607
+
608
+ with open(flash_image, "rb") as f:
609
+ header_data = f.read(FLASH_IMAGE_HEADER)
610
+ content_data = f.read()
611
+
612
+ with open(image_header_path, "wb") as f:
613
+ f.write(header_data)
614
+
615
+ with open(image_content_path, "wb") as f:
616
+ f.write(content_data)
617
+
618
+ flash_image_header_download = BinaryDownloader(
619
+ bin_file=image_header_path,
620
+ interface_type=self.interface_type,
621
+ serial_number=self.serial_number,
622
+ wait_timeout=self.wait_timeout,
623
+ write_timeout=self.write_timeout,
624
+ verbose=self.verbose,
625
+ # tclk_delay=self.tclk_delay,
626
+ # chunk_size=self.chunk_size,
627
+ )
628
+
629
+ flash_image_content_download = BinaryDownloader(
630
+ bin_file=image_content_path,
631
+ interface_type=self.interface_type,
632
+ serial_number=self.serial_number,
633
+ wait_timeout=self.wait_timeout,
634
+ write_timeout=self.write_timeout,
635
+ wait_for_resp=wait_for_resp,
636
+ verbose=self.verbose,
637
+ tclk_delay=self.tclk_delay,
638
+ chunk_size=self.chunk_size,
639
+ expected_resp_size=self.report_generator.get_report_struct_size(),
640
+ jlink_speed_khz=self.jlink_speed_khz,
641
+ )
642
+
643
+ # check flash status
644
+ if self.interface_type != self.SIMULATION:
645
+ # Read cfgap - use device-specific register class
646
+ life_cycle_state_reg = self._lifecycle_reg_class(
647
+ interface=self.interface_type,
648
+ serial_number=self.serial_number,
649
+ verbose=False,
650
+ )
651
+ life_cycle_state_reg.read_reg()
652
+ flash_status = life_cycle_state_reg.flash_status
653
+ # print(f"header: flash_status first read: {flash_status}", flush=True)
654
+
655
+ timeout_time = time.perf_counter() + self.erase_wait_timeout
656
+ timeout_occur = time.perf_counter() > timeout_time
657
+ # Wait until flash_status == 0 or flash_status == 3 or if timeout occur
658
+ # print("header: flash_status read in loop: ", end=" ", flush=True)
659
+ while (
660
+ flash_status != FLASH_STATUS.ready_for_header.value
661
+ and not timeout_occur
662
+ ):
663
+ time.sleep(0.1)
664
+ life_cycle_state_reg.read_reg()
665
+ flash_status = life_cycle_state_reg.flash_status
666
+ timeout_occur = time.perf_counter() > timeout_time
667
+ # print(f"{flash_status}", end=" ", flush=True)
668
+ life_cycle_state_reg.disconnect()
669
+ if timeout_occur:
670
+ self.error_message = "Timeout occur while waiting for acknowledge from device before download image header"
671
+ self._uniflash_update_progress(self.error_message, 0, True)
672
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
673
+ return False
674
+
675
+ # send image header
676
+ flash_image_header_download.daemon = True
677
+ flash_image_header_download.start()
678
+
679
+ while flash_image_header_download.is_alive():
680
+ flash_image_header_download.join(0.1)
681
+
682
+ error_code, error_msg = flash_image_header_download.download_status
683
+
684
+ if error_code > 0:
685
+ PROGRAMMER_PROGRAM_LOGGER.log(
686
+ self.log_level, "Successfully loaded binary"
687
+ )
688
+ else:
689
+ self.error_message = "Failed loading image flash header"
690
+ self._uniflash_update_progress(self.error_message, 0, True)
691
+ PROGRAMMER_PROGRAM_LOGGER.error(
692
+ f"Failed loading binary with error code: {error_code}\nError message: {error_msg}"
693
+ )
694
+ return False
695
+
696
+ # check flash status
697
+ if self.interface_type != self.SIMULATION:
698
+ # Added by Danil 9/11 for give programmer chance to update flash_status after download header
699
+ time.sleep(1)
700
+
701
+ # Read cfgap - use device-specific register class
702
+ life_cycle_state_reg = self._lifecycle_reg_class(
703
+ interface=self.interface_type,
704
+ serial_number=self.serial_number,
705
+ verbose=False,
706
+ )
707
+ life_cycle_state_reg.read_reg()
708
+ flash_status = life_cycle_state_reg.flash_status
709
+ # print(f"content: flash_status first read: {flash_status}", flush=True)
710
+
711
+ timeout_time = time.perf_counter() + self.erase_wait_timeout
712
+ timeout_occur = time.perf_counter() > timeout_time
713
+ # Wait until flash_status == 2 or flash_status == 3 or if timeout occur
714
+ # print("content: flash_status read in loop: ", end=" ", flush=True)
715
+ while (
716
+ flash_status != FLASH_STATUS.ready_for_content.value
717
+ and not timeout_occur
718
+ ):
719
+ time.sleep(0.1)
720
+ life_cycle_state_reg.read_reg()
721
+ flash_status = life_cycle_state_reg.flash_status
722
+ timeout_occur = time.perf_counter() > timeout_time
723
+ # print(f"{flash_status}", end=" ", flush=True)
724
+
725
+ life_cycle_state_reg.disconnect()
726
+ if timeout_occur:
727
+ self.error_message = "Timeout occur while waiting for acknowledge from device before download image content"
728
+ self._uniflash_update_progress(self.error_message, 0, True)
729
+ PROGRAMMER_PROGRAM_LOGGER.error(self.error_message)
730
+ return False
731
+
732
+ # send image content
733
+ flash_image_content_download.daemon = True
734
+ flash_image_content_download.start()
735
+
736
+ while flash_image_content_download.is_alive():
737
+ flash_image_content_download.join(0.1)
738
+
739
+ error_code, error_msg = flash_image_content_download.download_status
740
+
741
+ if error_code > 0:
742
+ PROGRAMMER_PROGRAM_LOGGER.log(
743
+ self.log_level, "Successfully loaded binary"
744
+ )
745
+ else:
746
+ self.error_message = f"Failed loading image flash content"
747
+ self._uniflash_update_progress(self.error_message, 0, True)
748
+ PROGRAMMER_PROGRAM_LOGGER.error(
749
+ f"Failed load binary with error code: {error_code}\nError message: {error_msg}"
750
+ )
751
+ return False
752
+
753
+ #################################################
754
+ ## Step 6 ##
755
+ ## Get response and print to the user ##
756
+ #################################################
757
+ self._uniflash_update_progress(f"Get response", 90)
758
+ if wait_for_resp:
759
+ # get response
760
+ if self.flash_images_list == []:
761
+ report_content_raw = prog_inst_downloader.resp
762
+ else:
763
+ report_content_raw = flash_image_content_download.resp
764
+
765
+ # generate report
766
+ if not self.report_generator.generate_report(report_content_raw):
767
+ self.error_message = self.report_generator.error_message
768
+ self._uniflash_update_progress(self.error_message, 0, True)
769
+ return False
770
+
771
+ self.rollback_mismatches = self.fib_utility.check_rollback_mismatches(
772
+ programming_components, self.report_generator.report_container.vendor_fuse_report, self.device_type
773
+ )
774
+
775
+ return True