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,357 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import pathlib
|
|
3
|
+
|
|
4
|
+
from communicator_core import (
|
|
5
|
+
BinaryDownloader,
|
|
6
|
+
DeviceLifeCycleNum,
|
|
7
|
+
DSSMStatus,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from flash_images_builder_core import PsramOption, FIBUtility
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from report import (
|
|
15
|
+
MemoryValidationReportGeneratorCC35XXE,
|
|
16
|
+
)
|
|
17
|
+
from utility import (
|
|
18
|
+
ProgrammerUtility,
|
|
19
|
+
get_lifecycle_state_reg_class,
|
|
20
|
+
)
|
|
21
|
+
except ImportError:
|
|
22
|
+
from .report import (
|
|
23
|
+
MemoryValidationReportGeneratorCC35XXE,
|
|
24
|
+
)
|
|
25
|
+
from .utility import (
|
|
26
|
+
ProgrammerUtility,
|
|
27
|
+
get_lifecycle_state_reg_class,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# uncomment for debug communicator code without build package communicator_core for every change
|
|
31
|
+
# if 'communicator' in sys.modules.keys():
|
|
32
|
+
# from communicator.communicator_core.core.cc35xx_config_ap import DeviceLifeCycleNum, DSSMStatus, LifeCycleStateReg
|
|
33
|
+
# from communicator.communicator_core.core.binary_downloader import BinaryDownloader
|
|
34
|
+
|
|
35
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER = logging.getLogger("partial-fuse-programming")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# note: 0x4110295c - hw life cycle address
|
|
39
|
+
class MemoryValidationTest:
|
|
40
|
+
SIMULATION = "DEMO"
|
|
41
|
+
XDS110 = "XDS110"
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
interface_type,
|
|
46
|
+
serial_number,
|
|
47
|
+
programmer_artifacts_path,
|
|
48
|
+
fib_artifacts_path,
|
|
49
|
+
device_type,
|
|
50
|
+
flash_type=None,
|
|
51
|
+
psram_type=PsramOption.NO_PSRAM.name,
|
|
52
|
+
enable_ota=False,
|
|
53
|
+
report_file_path=None,
|
|
54
|
+
reset_on_timeout=True,
|
|
55
|
+
path_to_tac=None,
|
|
56
|
+
wait_timeout=2,
|
|
57
|
+
write_timeout=0,
|
|
58
|
+
wait_for_resp=True,
|
|
59
|
+
verbose=False,
|
|
60
|
+
tclk_delay=4,
|
|
61
|
+
chunk_size=1085,
|
|
62
|
+
flash_radius_pass_value=15,
|
|
63
|
+
psram_radius_pass_value=10,
|
|
64
|
+
):
|
|
65
|
+
self.device_type = device_type
|
|
66
|
+
|
|
67
|
+
# Initialize the appropriate LifeCycleStateReg class based on device type
|
|
68
|
+
self._lifecycle_reg_class = get_lifecycle_state_reg_class(self.device_type)
|
|
69
|
+
|
|
70
|
+
self.flash_type = flash_type
|
|
71
|
+
self.enable_ota = enable_ota
|
|
72
|
+
self.psram_type = psram_type
|
|
73
|
+
self.fuses_dict = {}
|
|
74
|
+
self.prog_utility = ProgrammerUtility(
|
|
75
|
+
programmer_artifacts_path, fib_artifacts_path
|
|
76
|
+
)
|
|
77
|
+
self.fib_utility = FIBUtility(fib_artifacts_path)
|
|
78
|
+
|
|
79
|
+
self.path_to_tac = path_to_tac
|
|
80
|
+
if self.path_to_tac is None:
|
|
81
|
+
self.path_to_tac = self.prog_utility.get_default_activator(self.device_type)
|
|
82
|
+
|
|
83
|
+
self.tmp_folder = self.prog_utility.get_act_n_init_tmp_folder()
|
|
84
|
+
|
|
85
|
+
self.report_file_path = (
|
|
86
|
+
report_file_path
|
|
87
|
+
if report_file_path
|
|
88
|
+
else (pathlib.Path(self.tmp_folder) / "memory_validation_test_report.txt")
|
|
89
|
+
)
|
|
90
|
+
self.fuses_json_file_path = (
|
|
91
|
+
pathlib.Path(self.tmp_folder) / "fuse_prog_inst_param.json"
|
|
92
|
+
)
|
|
93
|
+
self.programming_unsign_image_path = ""
|
|
94
|
+
|
|
95
|
+
self.reset_on_timeout = reset_on_timeout
|
|
96
|
+
self.interface_type = interface_type
|
|
97
|
+
self.serial_number = serial_number
|
|
98
|
+
self.wait_timeout = wait_timeout
|
|
99
|
+
self.write_timeout = write_timeout
|
|
100
|
+
self.wait_for_resp = wait_for_resp
|
|
101
|
+
|
|
102
|
+
self.tclk_delay = tclk_delay
|
|
103
|
+
self.chunk_size = chunk_size
|
|
104
|
+
|
|
105
|
+
self.flash_radius_pass_value = flash_radius_pass_value
|
|
106
|
+
self.psram_radius_pass_value = psram_radius_pass_value
|
|
107
|
+
|
|
108
|
+
self.verbose = verbose
|
|
109
|
+
self.log_level = logging.INFO if verbose else logging.DEBUG
|
|
110
|
+
|
|
111
|
+
self.error_message = ""
|
|
112
|
+
|
|
113
|
+
# TODO: temporary - CC37XXR uses CC35XXE report generator until CC37XXR specific generators are available
|
|
114
|
+
# Select report generator based on device type
|
|
115
|
+
self.report_generator = MemoryValidationReportGeneratorCC35XXE(
|
|
116
|
+
report_file_path=self.report_file_path,
|
|
117
|
+
programmer_artifacts_path=programmer_artifacts_path,
|
|
118
|
+
fib_artifacts_path=fib_artifacts_path,
|
|
119
|
+
verbose=self.verbose,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def memory_validation_test(self):
|
|
123
|
+
|
|
124
|
+
# delete report file if exist
|
|
125
|
+
report_path = pathlib.Path(self.report_file_path)
|
|
126
|
+
if report_path.exists():
|
|
127
|
+
try:
|
|
128
|
+
report_path.unlink()
|
|
129
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.debug(
|
|
130
|
+
"Report file deleted successfully"
|
|
131
|
+
)
|
|
132
|
+
except Exception as e:
|
|
133
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.warning(
|
|
134
|
+
f"Failed to delete report file: {e}"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
#################################################
|
|
138
|
+
## Step 0 ##
|
|
139
|
+
## check that tac file exist ##
|
|
140
|
+
#################################################
|
|
141
|
+
|
|
142
|
+
self.path_to_tac = self.prog_utility.fix_path(self.path_to_tac)
|
|
143
|
+
res = self.prog_utility.file_path_exist(self.path_to_tac, "TI Activation")
|
|
144
|
+
if res is not None:
|
|
145
|
+
self.error_message = res
|
|
146
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.error(self.error_message)
|
|
147
|
+
return False
|
|
148
|
+
|
|
149
|
+
#################################################
|
|
150
|
+
## Step 1 ##
|
|
151
|
+
## build prog inst image ##
|
|
152
|
+
#################################################
|
|
153
|
+
|
|
154
|
+
# get jsons file by flash type
|
|
155
|
+
ext_flash_dir_path = self.fib_utility.get_ext_flash_dir_path()
|
|
156
|
+
|
|
157
|
+
self.xspi_json, self.otfde_json, self.ext_mem_json = (
|
|
158
|
+
self.prog_utility.get_flash_jsons(
|
|
159
|
+
flash_type_files_folder=ext_flash_dir_path,
|
|
160
|
+
flash_device=self.flash_type,
|
|
161
|
+
enable_ota=self.enable_ota,
|
|
162
|
+
tmp_dir_path=self.tmp_folder,
|
|
163
|
+
psram_type=self.psram_type,
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# update fuse params
|
|
168
|
+
self.fuses_dict["rot"] = "FF" * 32
|
|
169
|
+
self.prog_utility.create_new_fuses_json_file(
|
|
170
|
+
self.fuses_dict, self.fuses_json_file_path
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# build programming image
|
|
174
|
+
self.programming_unsign_image_path, self.programming_image_to_sign_out_path = (
|
|
175
|
+
self.prog_utility.build_programming_image(
|
|
176
|
+
version="0.0.1.0",
|
|
177
|
+
pub_key_path=None,
|
|
178
|
+
activation_type=None,
|
|
179
|
+
dir_out_path=self.tmp_folder,
|
|
180
|
+
fuses_programming_instructions=self.fuses_json_file_path,
|
|
181
|
+
flash_discovery_config_xspi=self.xspi_json,
|
|
182
|
+
flash_discovery_config_otfde=self.otfde_json,
|
|
183
|
+
flash_discovery_config_ext_mem=self.ext_mem_json,
|
|
184
|
+
device=self.device_type,
|
|
185
|
+
logging_level=self.log_level,
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
#################################################
|
|
190
|
+
## Step 1 ##
|
|
191
|
+
## reset device and download TI Bootloader ##
|
|
192
|
+
#################################################
|
|
193
|
+
|
|
194
|
+
tbl_download = BinaryDownloader(
|
|
195
|
+
bin_file=self.path_to_tac,
|
|
196
|
+
interface_type=self.interface_type,
|
|
197
|
+
serial_number=self.serial_number,
|
|
198
|
+
wait_timeout=self.wait_timeout,
|
|
199
|
+
write_timeout=self.write_timeout,
|
|
200
|
+
verbose=self.verbose,
|
|
201
|
+
tclk_delay=self.tclk_delay,
|
|
202
|
+
chunk_size=self.chunk_size,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# reset device
|
|
206
|
+
tbl_download.device.reset_device()
|
|
207
|
+
|
|
208
|
+
# Download TI bootloader
|
|
209
|
+
tbl_download.daemon = True
|
|
210
|
+
tbl_download.start()
|
|
211
|
+
|
|
212
|
+
while tbl_download.is_alive():
|
|
213
|
+
tbl_download.join(0.1)
|
|
214
|
+
|
|
215
|
+
error_code, error_msg = tbl_download.download_status
|
|
216
|
+
|
|
217
|
+
if error_code > 0:
|
|
218
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.log(
|
|
219
|
+
self.log_level, "Successfully loaded binary"
|
|
220
|
+
)
|
|
221
|
+
else:
|
|
222
|
+
self.error_message = f"Failed loading 'TI Activator' image"
|
|
223
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.error(
|
|
224
|
+
f"Fail load binary with error code: {error_code}\nError message: {error_msg}"
|
|
225
|
+
)
|
|
226
|
+
return False
|
|
227
|
+
|
|
228
|
+
#################################################
|
|
229
|
+
## Step 2 ##
|
|
230
|
+
## read CFGAP and check life-cycle/DSSM status ##
|
|
231
|
+
#################################################
|
|
232
|
+
|
|
233
|
+
if self.interface_type != self.SIMULATION:
|
|
234
|
+
# Read cfgap - use device-specific register class
|
|
235
|
+
life_cycle_state_reg = self._lifecycle_reg_class(
|
|
236
|
+
interface=self.interface_type,
|
|
237
|
+
serial_number=self.serial_number,
|
|
238
|
+
verbose=self.verbose,
|
|
239
|
+
)
|
|
240
|
+
life_cycle_state_reg.read_reg()
|
|
241
|
+
life_cycle = life_cycle_state_reg.life_cycle_sw_coded
|
|
242
|
+
dssm_status = life_cycle_state_reg.dssm_status
|
|
243
|
+
life_cycle_state_reg.disconnect()
|
|
244
|
+
|
|
245
|
+
# Check if life cycle is one of allowed_life_cycle
|
|
246
|
+
allowed_life_cycle = [
|
|
247
|
+
DeviceLifeCycleNum.OPERATIONAL,
|
|
248
|
+
DeviceLifeCycleNum.RMA_HW_ANALYSIS,
|
|
249
|
+
DeviceLifeCycleNum.RMA_FAILIURE_ANALYSIS,
|
|
250
|
+
]
|
|
251
|
+
if life_cycle not in allowed_life_cycle:
|
|
252
|
+
self.error_message = "Life cycle is not valid"
|
|
253
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.error(
|
|
254
|
+
f"Process is stopped. Life cycle {DeviceLifeCycleNum(life_cycle).name} is not valid."
|
|
255
|
+
)
|
|
256
|
+
return False
|
|
257
|
+
|
|
258
|
+
# Check if dssm status is DSSM_READY
|
|
259
|
+
if not dssm_status == DSSMStatus.DSSM_READY:
|
|
260
|
+
self.error_message = f"Device is not ready for partial fuse programming"
|
|
261
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.error(self.error_message)
|
|
262
|
+
return False
|
|
263
|
+
|
|
264
|
+
#################################################
|
|
265
|
+
## Step 3 ##
|
|
266
|
+
## download programming image ##
|
|
267
|
+
#################################################
|
|
268
|
+
|
|
269
|
+
prog_inst_downloader = BinaryDownloader(
|
|
270
|
+
bin_file=self.programming_unsign_image_path,
|
|
271
|
+
interface_type=self.interface_type,
|
|
272
|
+
serial_number=self.serial_number,
|
|
273
|
+
wait_timeout=self.wait_timeout,
|
|
274
|
+
write_timeout=self.write_timeout,
|
|
275
|
+
wait_for_resp=self.wait_for_resp,
|
|
276
|
+
verbose=self.verbose,
|
|
277
|
+
expected_resp_size=self.report_generator.get_report_struct_size(),
|
|
278
|
+
tclk_delay=self.tclk_delay,
|
|
279
|
+
chunk_size=self.chunk_size,
|
|
280
|
+
)
|
|
281
|
+
prog_inst_downloader.daemon = True
|
|
282
|
+
prog_inst_downloader.start()
|
|
283
|
+
|
|
284
|
+
while prog_inst_downloader.is_alive():
|
|
285
|
+
prog_inst_downloader.join(0.1)
|
|
286
|
+
|
|
287
|
+
error_code, error_msg = prog_inst_downloader.download_status
|
|
288
|
+
|
|
289
|
+
if error_code > 0:
|
|
290
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.log(
|
|
291
|
+
self.log_level, "Successfully loaded binary"
|
|
292
|
+
)
|
|
293
|
+
else:
|
|
294
|
+
self.error_message = f"Failed loading 'Programming Instruction' image"
|
|
295
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.error(
|
|
296
|
+
f"Failed loading binary with error code: {error_code}\nError message: {error_msg}"
|
|
297
|
+
)
|
|
298
|
+
return False
|
|
299
|
+
|
|
300
|
+
#################################################
|
|
301
|
+
## Step 4 ##
|
|
302
|
+
## get response and print to the user ##
|
|
303
|
+
#################################################
|
|
304
|
+
|
|
305
|
+
if self.wait_for_resp:
|
|
306
|
+
# get response
|
|
307
|
+
report_content_raw = prog_inst_downloader.resp
|
|
308
|
+
|
|
309
|
+
# generate report
|
|
310
|
+
if not self.report_generator.generate_report(report_content_raw):
|
|
311
|
+
self.error_message = self.report_generator.error_message
|
|
312
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.info(
|
|
313
|
+
"Memory Validation Test Process: FAILED"
|
|
314
|
+
)
|
|
315
|
+
return False
|
|
316
|
+
|
|
317
|
+
# Memory validation was for psram
|
|
318
|
+
if self.psram_type != PsramOption.NO_PSRAM.name:
|
|
319
|
+
psarm_memory_validation_result = (
|
|
320
|
+
self.report_generator.report_container.psarm_memory_validation_result
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
if not psarm_memory_validation_result.valid:
|
|
324
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.info(
|
|
325
|
+
"Memory Validation Test Process: FAILED - PSRAM test valid is False"
|
|
326
|
+
)
|
|
327
|
+
return False
|
|
328
|
+
|
|
329
|
+
if psarm_memory_validation_result.Radius < self.psram_radius_pass_value:
|
|
330
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.info(
|
|
331
|
+
f"Memory Validation Test Process: FAILED - PSRAM radius {psarm_memory_validation_result.Radius} below threshold {self.psram_radius_pass_value}"
|
|
332
|
+
)
|
|
333
|
+
return False
|
|
334
|
+
|
|
335
|
+
# Memory validation was for flash
|
|
336
|
+
else:
|
|
337
|
+
flash_memory_validation_result = (
|
|
338
|
+
self.report_generator.report_container.flash_memory_validation_result
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
if not flash_memory_validation_result.valid:
|
|
342
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.info(
|
|
343
|
+
"Memory Validation Test Process: FAILED - FLASH test valid is False"
|
|
344
|
+
)
|
|
345
|
+
return False
|
|
346
|
+
|
|
347
|
+
if flash_memory_validation_result.Radius < self.flash_radius_pass_value:
|
|
348
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.info(
|
|
349
|
+
f"Memory Validation Test Process: FAILED - FLASH radius {flash_memory_validation_result.Radius} below threshold {self.flash_radius_pass_value}"
|
|
350
|
+
)
|
|
351
|
+
return False
|
|
352
|
+
|
|
353
|
+
PROG_MEMORY_VALIDATION_TEST_LOGGER.info(
|
|
354
|
+
"Memory Validation Test Process: SUCCEEDED"
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
return True
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import pathlib
|
|
3
|
+
|
|
4
|
+
from communicator_core import (
|
|
5
|
+
BinaryDownloader,
|
|
6
|
+
DeviceLifeCycleNum,
|
|
7
|
+
DSSMStatus,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from flash_images_builder_core import (
|
|
11
|
+
FIBUtility,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
from report import (
|
|
16
|
+
ProgrammingReportGeneratorCC35XXE,
|
|
17
|
+
)
|
|
18
|
+
from utility import (
|
|
19
|
+
ProgrammerUtility,
|
|
20
|
+
get_lifecycle_state_reg_class,
|
|
21
|
+
)
|
|
22
|
+
except ImportError:
|
|
23
|
+
from .report import (
|
|
24
|
+
ProgrammingReportGeneratorCC35XXE,
|
|
25
|
+
)
|
|
26
|
+
from .utility import (
|
|
27
|
+
ProgrammerUtility,
|
|
28
|
+
get_lifecycle_state_reg_class,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# uncomment for debug communicator code without build package communicator_core for every change
|
|
32
|
+
# if 'communicator' in sys.modules.keys():
|
|
33
|
+
# from communicator.communicator_core.core.cc35xx_config_ap import DeviceLifeCycleNum, DSSMStatus, LifeCycleStateReg
|
|
34
|
+
# from communicator.communicator_core.core.binary_downloader import BinaryDownloader
|
|
35
|
+
|
|
36
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER = logging.getLogger("partial-fuse-programming")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# note: 0x4110295c - hw life cycle address
|
|
40
|
+
class PartialFuseProgramming:
|
|
41
|
+
SIMULATION = "DEMO"
|
|
42
|
+
XDS110 = "XDS110"
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
interface_type,
|
|
47
|
+
serial_number,
|
|
48
|
+
programmer_artifacts_path,
|
|
49
|
+
fib_artifacts_path,
|
|
50
|
+
device_type,
|
|
51
|
+
restrict_ini=0,
|
|
52
|
+
country_code=0,
|
|
53
|
+
crda_code_enable=0,
|
|
54
|
+
mac_address="00:00:00:00:00:00",
|
|
55
|
+
wifi6_disable=0,
|
|
56
|
+
flash_type=None,
|
|
57
|
+
report_file_path=None,
|
|
58
|
+
reset_on_timeout=True,
|
|
59
|
+
path_to_tac=None,
|
|
60
|
+
wait_timeout=2,
|
|
61
|
+
write_timeout=0,
|
|
62
|
+
wait_for_resp=True,
|
|
63
|
+
verbose=False,
|
|
64
|
+
tclk_delay=4,
|
|
65
|
+
chunk_size=1085,
|
|
66
|
+
):
|
|
67
|
+
# fuse configurarions --> exclude athutentication_enable & app_otp
|
|
68
|
+
self.restrict_ini = restrict_ini
|
|
69
|
+
self.country_code = country_code
|
|
70
|
+
self.mac_address = mac_address
|
|
71
|
+
self.wifi6_disable = wifi6_disable
|
|
72
|
+
self.flash_type = flash_type
|
|
73
|
+
self.prog_utility = ProgrammerUtility(
|
|
74
|
+
programmer_artifacts_path, fib_artifacts_path
|
|
75
|
+
)
|
|
76
|
+
self.fib_utility = FIBUtility(fib_artifacts_path)
|
|
77
|
+
self.mac_address_31_0, self.mac_address_47_32 = (
|
|
78
|
+
self.prog_utility.split_mac_address(self.mac_address)
|
|
79
|
+
)
|
|
80
|
+
self.crda_code_enable = crda_code_enable
|
|
81
|
+
self.device_type = device_type
|
|
82
|
+
|
|
83
|
+
# Initialize the appropriate LifeCycleStateReg class based on device type
|
|
84
|
+
self._lifecycle_reg_class = get_lifecycle_state_reg_class(self.device_type)
|
|
85
|
+
|
|
86
|
+
self.fuses_dict = {}
|
|
87
|
+
self.path_to_tac = path_to_tac
|
|
88
|
+
if self.path_to_tac is None:
|
|
89
|
+
self.path_to_tac = self.prog_utility.get_default_activator(self.device_type)
|
|
90
|
+
|
|
91
|
+
self.tmp_folder = self.prog_utility.get_act_n_init_tmp_folder()
|
|
92
|
+
|
|
93
|
+
self.report_file_path = (
|
|
94
|
+
report_file_path
|
|
95
|
+
if report_file_path
|
|
96
|
+
else (pathlib.Path(self.tmp_folder) / "partial_fuse_programming_report.txt")
|
|
97
|
+
)
|
|
98
|
+
self.fuses_json_file_path = (
|
|
99
|
+
pathlib.Path(self.tmp_folder) / "fuse_prog_inst_param.json"
|
|
100
|
+
)
|
|
101
|
+
self.programming_unsign_image_path = ""
|
|
102
|
+
|
|
103
|
+
self.reset_on_timeout = reset_on_timeout
|
|
104
|
+
self.interface_type = interface_type
|
|
105
|
+
self.serial_number = serial_number
|
|
106
|
+
self.wait_timeout = wait_timeout
|
|
107
|
+
self.write_timeout = write_timeout
|
|
108
|
+
self.wait_for_resp = wait_for_resp
|
|
109
|
+
|
|
110
|
+
self.tclk_delay = tclk_delay
|
|
111
|
+
self.chunk_size = chunk_size
|
|
112
|
+
|
|
113
|
+
self.verbose = verbose
|
|
114
|
+
self.log_level = logging.INFO if verbose else logging.DEBUG
|
|
115
|
+
|
|
116
|
+
self.error_message = ""
|
|
117
|
+
|
|
118
|
+
# TODO: temporary - CC37XXR uses CC35XXE report generator until CC37XXR specific generators are available
|
|
119
|
+
# Select report generator based on device type
|
|
120
|
+
self.report_generator = ProgrammingReportGeneratorCC35XXE(
|
|
121
|
+
programmer_artifacts_path=programmer_artifacts_path,
|
|
122
|
+
fib_artifacts_path=fib_artifacts_path,
|
|
123
|
+
report_file_path=self.report_file_path,
|
|
124
|
+
verbose=self.verbose,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def partial_fuse_programming_update(self):
|
|
128
|
+
|
|
129
|
+
# delete report file if exist
|
|
130
|
+
report_path = pathlib.Path(self.report_file_path)
|
|
131
|
+
if report_path.exists():
|
|
132
|
+
try:
|
|
133
|
+
report_path.unlink()
|
|
134
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.debug("Report file deleted successfully")
|
|
135
|
+
except Exception as e:
|
|
136
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.warning(
|
|
137
|
+
f"Failed to delete report file: {e}"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
#################################################
|
|
141
|
+
## Step 0 ##
|
|
142
|
+
## check that tac file exist ##
|
|
143
|
+
#################################################
|
|
144
|
+
|
|
145
|
+
self.path_to_tac = self.prog_utility.fix_path(self.path_to_tac)
|
|
146
|
+
res = self.prog_utility.file_path_exist(self.path_to_tac, "TI Activation")
|
|
147
|
+
if res is not None:
|
|
148
|
+
self.error_message = res
|
|
149
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.error(self.error_message)
|
|
150
|
+
return False
|
|
151
|
+
|
|
152
|
+
#################################################
|
|
153
|
+
## Step 1 ##
|
|
154
|
+
## build prog inst image ##
|
|
155
|
+
#################################################
|
|
156
|
+
|
|
157
|
+
# get jsons file by flash type
|
|
158
|
+
ext_flash_dir_path = self.fib_utility.get_ext_flash_dir_path()
|
|
159
|
+
self.xspi_json, self.otfde_json, self.ext_mem_json = (
|
|
160
|
+
self.prog_utility.get_flash_jsons(
|
|
161
|
+
flash_type_files_folder=ext_flash_dir_path,
|
|
162
|
+
flash_device=self.flash_type,
|
|
163
|
+
tmp_dir_path=self.tmp_folder,
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# update fuse params
|
|
168
|
+
self.fuses_dict["rot"] = "00" * 32
|
|
169
|
+
self.fuses_dict["wifi6_disable"] = self.wifi6_disable
|
|
170
|
+
self.fuses_dict["vendor_restricted_ini"] = self.restrict_ini
|
|
171
|
+
self.fuses_dict["mac_address_31_0"] = self.mac_address_31_0
|
|
172
|
+
self.fuses_dict["mac_address_47_32"] = self.mac_address_47_32
|
|
173
|
+
self.fuses_dict["crda_country_code"] = self.country_code
|
|
174
|
+
self.fuses_dict["crda_code_enable"] = self.crda_code_enable
|
|
175
|
+
|
|
176
|
+
self.prog_utility.create_new_fuses_json_file(
|
|
177
|
+
self.fuses_dict, self.fuses_json_file_path
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# build programming image
|
|
181
|
+
self.programming_unsign_image_path, self.programming_image_to_sign_out_path = (
|
|
182
|
+
self.prog_utility.build_programming_image(
|
|
183
|
+
version="0.0.1.0",
|
|
184
|
+
pub_key_path=None,
|
|
185
|
+
activation_type=None,
|
|
186
|
+
dir_out_path=self.tmp_folder,
|
|
187
|
+
fuses_programming_instructions=self.fuses_json_file_path,
|
|
188
|
+
flash_discovery_config_xspi=self.xspi_json,
|
|
189
|
+
flash_discovery_config_otfde=self.otfde_json,
|
|
190
|
+
flash_discovery_config_ext_mem=self.ext_mem_json,
|
|
191
|
+
device=self.device_type,
|
|
192
|
+
logging_level=self.log_level,
|
|
193
|
+
)
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
#################################################
|
|
197
|
+
## Step 1 ##
|
|
198
|
+
## reset device and download TI Bootloader ##
|
|
199
|
+
#################################################
|
|
200
|
+
|
|
201
|
+
tbl_download = BinaryDownloader(
|
|
202
|
+
bin_file=self.path_to_tac,
|
|
203
|
+
interface_type=self.interface_type,
|
|
204
|
+
serial_number=self.serial_number,
|
|
205
|
+
wait_timeout=self.wait_timeout,
|
|
206
|
+
write_timeout=self.write_timeout,
|
|
207
|
+
verbose=self.verbose,
|
|
208
|
+
tclk_delay=self.tclk_delay,
|
|
209
|
+
chunk_size=self.chunk_size,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# reset device
|
|
213
|
+
tbl_download.device.reset_device()
|
|
214
|
+
|
|
215
|
+
# Download TI bootloader
|
|
216
|
+
tbl_download.daemon = True
|
|
217
|
+
tbl_download.start()
|
|
218
|
+
|
|
219
|
+
while tbl_download.is_alive():
|
|
220
|
+
tbl_download.join(0.1)
|
|
221
|
+
|
|
222
|
+
error_code, error_msg = tbl_download.download_status
|
|
223
|
+
|
|
224
|
+
if error_code > 0:
|
|
225
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.log(
|
|
226
|
+
self.log_level, "Successfully loaded binary"
|
|
227
|
+
)
|
|
228
|
+
else:
|
|
229
|
+
self.error_message = f"Failed loading 'TI Activator' image"
|
|
230
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.error(
|
|
231
|
+
f"Fail load binary with error code: {error_code}\nError message: {error_msg}"
|
|
232
|
+
)
|
|
233
|
+
return False
|
|
234
|
+
|
|
235
|
+
#################################################
|
|
236
|
+
## Step 2 ##
|
|
237
|
+
## read CFGAP and check life-cycle/DSSM status ##
|
|
238
|
+
#################################################
|
|
239
|
+
|
|
240
|
+
if self.interface_type != self.SIMULATION:
|
|
241
|
+
# Read cfgap - use device-specific register class
|
|
242
|
+
life_cycle_state_reg = self._lifecycle_reg_class(
|
|
243
|
+
interface=self.interface_type,
|
|
244
|
+
serial_number=self.serial_number,
|
|
245
|
+
verbose=self.verbose,
|
|
246
|
+
)
|
|
247
|
+
life_cycle_state_reg.read_reg()
|
|
248
|
+
life_cycle = life_cycle_state_reg.life_cycle_sw_coded
|
|
249
|
+
dssm_status = life_cycle_state_reg.dssm_status
|
|
250
|
+
life_cycle_state_reg.disconnect()
|
|
251
|
+
|
|
252
|
+
# Check if life cycle is one of allowed_life_cycle
|
|
253
|
+
allowed_life_cycle = [
|
|
254
|
+
DeviceLifeCycleNum.OPERATIONAL,
|
|
255
|
+
DeviceLifeCycleNum.RMA_HW_ANALYSIS,
|
|
256
|
+
DeviceLifeCycleNum.RMA_FAILIURE_ANALYSIS,
|
|
257
|
+
]
|
|
258
|
+
if life_cycle not in allowed_life_cycle:
|
|
259
|
+
self.error_message = "Life cycle is not valid"
|
|
260
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.error(
|
|
261
|
+
f"Process is stopped. Life cycle {DeviceLifeCycleNum(life_cycle).name} is not valid."
|
|
262
|
+
)
|
|
263
|
+
return False
|
|
264
|
+
|
|
265
|
+
# Check if dssm status is DSSM_READY
|
|
266
|
+
if not dssm_status == DSSMStatus.DSSM_READY:
|
|
267
|
+
self.error_message = f"Device is not ready for partial fuse programming"
|
|
268
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.error(self.error_message)
|
|
269
|
+
return False
|
|
270
|
+
|
|
271
|
+
#################################################
|
|
272
|
+
## Step 3 ##
|
|
273
|
+
## download programming image ##
|
|
274
|
+
#################################################
|
|
275
|
+
|
|
276
|
+
prog_inst_downloader = BinaryDownloader(
|
|
277
|
+
bin_file=self.programming_unsign_image_path,
|
|
278
|
+
interface_type=self.interface_type,
|
|
279
|
+
serial_number=self.serial_number,
|
|
280
|
+
wait_timeout=self.wait_timeout,
|
|
281
|
+
write_timeout=self.write_timeout,
|
|
282
|
+
wait_for_resp=self.wait_for_resp,
|
|
283
|
+
verbose=self.verbose,
|
|
284
|
+
expected_resp_size=self.report_generator.get_report_struct_size(),
|
|
285
|
+
tclk_delay=self.tclk_delay,
|
|
286
|
+
chunk_size=self.chunk_size,
|
|
287
|
+
)
|
|
288
|
+
prog_inst_downloader.daemon = True
|
|
289
|
+
prog_inst_downloader.start()
|
|
290
|
+
|
|
291
|
+
while prog_inst_downloader.is_alive():
|
|
292
|
+
prog_inst_downloader.join(0.1)
|
|
293
|
+
|
|
294
|
+
error_code, error_msg = prog_inst_downloader.download_status
|
|
295
|
+
|
|
296
|
+
if error_code > 0:
|
|
297
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.log(
|
|
298
|
+
self.log_level, "Successfully loaded binary"
|
|
299
|
+
)
|
|
300
|
+
else:
|
|
301
|
+
self.error_message = f"Failed loading 'Programming Instruction' image"
|
|
302
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.error(
|
|
303
|
+
f"Failed loading binary with error code: {error_code}\nError message: {error_msg}"
|
|
304
|
+
)
|
|
305
|
+
return False
|
|
306
|
+
|
|
307
|
+
#################################################
|
|
308
|
+
## Step 4 ##
|
|
309
|
+
## get response and print to the user ##
|
|
310
|
+
#################################################
|
|
311
|
+
|
|
312
|
+
if self.wait_for_resp:
|
|
313
|
+
# get response
|
|
314
|
+
report_content_raw = prog_inst_downloader.resp
|
|
315
|
+
|
|
316
|
+
# generate report
|
|
317
|
+
if not self.report_generator.generate_report(report_content_raw):
|
|
318
|
+
self.error_message = self.report_generator.error_message
|
|
319
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.info(
|
|
320
|
+
"Partial Fuse Programming Process: FAILED"
|
|
321
|
+
)
|
|
322
|
+
return False
|
|
323
|
+
|
|
324
|
+
request_validation_status = (
|
|
325
|
+
self.report_generator.report_container.request_validation_status
|
|
326
|
+
)
|
|
327
|
+
if any(
|
|
328
|
+
[
|
|
329
|
+
request_validation_status.fuse_programming_instructions_alignment_verify_pass,
|
|
330
|
+
request_validation_status.recoverable_fault,
|
|
331
|
+
request_validation_status.non_recoverable_failure,
|
|
332
|
+
]
|
|
333
|
+
):
|
|
334
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.info(
|
|
335
|
+
"Partial Fuse Programming Process: FAILED"
|
|
336
|
+
)
|
|
337
|
+
return False
|
|
338
|
+
|
|
339
|
+
PROGRAMMER_PARTIAL_FUSE_LOGGER.info(
|
|
340
|
+
"Partial Fuse Programming Process: SUCCEEDED"
|
|
341
|
+
)
|
|
342
|
+
return True
|