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.
- programmer_core/__init__.py +22 -0
- programmer_core/activate_device.py +246 -0
- programmer_core/adapters.py +23 -0
- programmer_core/constants.py +50 -0
- programmer_core/debug_device.py +278 -0
- programmer_core/detect_flash_type.py +316 -0
- programmer_core/enter_rma.py +264 -0
- programmer_core/factory_program_device.py +667 -0
- programmer_core/full_flash_erase.py +268 -0
- programmer_core/get_fuse_data.py +277 -0
- programmer_core/memory_validation_test.py +357 -0
- programmer_core/partial_fuse_programming.py +342 -0
- programmer_core/program_device.py +775 -0
- programmer_core/query_device.py +274 -0
- programmer_core/report.py +921 -0
- programmer_core/utility.py +1822 -0
- programmer_core-1.0.29.dist-info/METADATA +146 -0
- programmer_core-1.0.29.dist-info/RECORD +20 -0
- programmer_core-1.0.29.dist-info/WHEEL +5 -0
- programmer_core-1.0.29.dist-info/top_level.txt +1 -0
|
@@ -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
|