mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
234 lines
8.0 KiB
Python
Executable File
234 lines
8.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
recovery.py
|
|
|
|
Support
|
|
- SEROM Recovery mode
|
|
- Allows updating of the MRAM through SEROM
|
|
- This is always ISP mode.
|
|
__author__ = ""
|
|
__copyright__ = "ALIF Seminconductor"
|
|
__version__ = "0.1.0"
|
|
__status__ = "Dev"
|
|
|
|
TODO:
|
|
- baud rate should be set to the SEROM default
|
|
"""
|
|
# pylint: disable=unused-argument, invalid-name, bare-except
|
|
import sys
|
|
sys.path.append("./isp")
|
|
from isp_protocol import *
|
|
from isp_core import *
|
|
from isp_util import *
|
|
import utils.config
|
|
from utils.config import *
|
|
from utils.user_validations import validateArgList
|
|
import device_probe
|
|
import time
|
|
|
|
# Probe error codes
|
|
PROBE_OK = 0
|
|
PROBE_SEROM = 1
|
|
PROBE_SERAM = 2
|
|
PROBE_NO_MESSAGE= 3
|
|
|
|
EXIT_WITH_ERROR = 1
|
|
|
|
BRING_UP_MODE = 1
|
|
|
|
def write_mram(isp, fileName, destAddress, verbose_display):
|
|
"""
|
|
write_mram - use ISP method to write MRAM
|
|
"""
|
|
try:
|
|
f = open(fileName, 'rb')
|
|
except IOError as e:
|
|
print('[ERROR] {0}'.format(e))
|
|
sys.exit(EXIT_WITH_ERROR)
|
|
with f:
|
|
fileSize = file_get_size(f)
|
|
# print("FILESIZE = %d" %fileSize)
|
|
|
|
# SEROM Recovery uses an Offset rather than an address
|
|
MRAM_BASE_ADDRESS = utils.config.MRAM_BASE_ADDRESS
|
|
offset = 0
|
|
data_size = 16
|
|
writeAddress = int(destAddress,base=16) - MRAM_BASE_ADDRESS
|
|
|
|
# print("Actual offset = ", hex(writeAddress))
|
|
number_of_blocks = fileSize // data_size
|
|
left_over_blocks = fileSize % data_size
|
|
|
|
start_time = time.time()
|
|
while number_of_blocks != 0:
|
|
f.seek(offset)
|
|
mram_line = f.read(data_size)
|
|
|
|
if verbose_display is False:
|
|
progress_bar(fileName,offset+data_size,fileSize)
|
|
message = isp_mram_write(isp,writeAddress,mram_line)
|
|
|
|
number_of_blocks = number_of_blocks - 1
|
|
offset = offset + data_size
|
|
writeAddress = writeAddress + data_size # increment by 16
|
|
if isp.CTRLCHandler.Handler_exit():
|
|
print("[INFO] CTRL-C")
|
|
break
|
|
|
|
end_time = time.time()
|
|
print("\r")
|
|
|
|
if verbose_display is False:
|
|
print("[INFO] recovery time {:10.2f} seconds".format(end_time-start_time))
|
|
|
|
f.close()
|
|
|
|
def checkTargetWithSelection(targetDescription, targetRevision,
|
|
selectedDescription, selectedRevision):
|
|
"""
|
|
Check target selection
|
|
"""
|
|
partIsDifferent = False
|
|
if targetDescription != selectedDescription:
|
|
print('Connected target is not the default Part#')
|
|
partIsDifferent = True
|
|
|
|
if targetRevision != selectedRevision:
|
|
print('Connected target is not the default Revision')
|
|
partIsDifferent = True
|
|
|
|
if partIsDifferent:
|
|
try:
|
|
answer = input('Do you want to set this part as default? (y/n): ')
|
|
except EOFError as e:
|
|
print('\nUser aborted the process')
|
|
sys.exit()
|
|
|
|
if answer.lower() == 'y' or answer.lower() == 'yes':
|
|
save_global_config(targetDescription, targetRevision)
|
|
|
|
def recovery_action_no_reset(isp):
|
|
"""
|
|
Recover MRAM via SEROM. Do not reset the device at the end.
|
|
"""
|
|
# probe the device before update
|
|
device = device_probe.device_get_attributes(isp)
|
|
# check SERAM is the bootloader stage
|
|
print('Bootloader stage: ' + device_probe.STAGE_TEXT[device.stage])
|
|
if device.stage == device_probe.STAGE_SERAM:
|
|
print('[ERROR] Device not in Recovery mode, use updateSystemPackage Tool')
|
|
sys.exit(EXIT_WITH_ERROR)
|
|
|
|
if device.revision == 'B2': #Device Part# is not retrieved by SEROM in B2
|
|
# load parameters based on Part# selected in tools-config
|
|
load_global_config()
|
|
print('Device Revision: ' + device.revision)
|
|
else:
|
|
if ord(device.part_number[:1]) == 0: # blank Part#
|
|
if BRING_UP_MODE:
|
|
print('Bring Up mode - Blank part detected!')
|
|
if device.revision in ['B0','B2','B3','B4']: # Ensemble
|
|
device.part_number = 'AE722F80F55D5LS'
|
|
elif device.revision in ['EG']: # Eagle A0
|
|
device.part_number = 'AE722F80F55D5EG'
|
|
device.revision = 'A0'
|
|
elif device.revision in ['B1','A0']: # Balletto B1C / E1C
|
|
device.part_number = 'AB1C1F4M51820PH'
|
|
else:
|
|
print('[ERROR] Revision is not reconginzed', device.revision)
|
|
sys.exit(EXIT_WITH_ERROR)
|
|
else:
|
|
print('[ERROR] There is no Part# in the device!')
|
|
sys.exit(EXIT_WITH_ERROR)
|
|
|
|
# selected device from global-cfg.db
|
|
selectedDescription = utils.config.DEVICE_PART_NUMBER
|
|
selectedRevision = utils.config.DEVICE_REVISION
|
|
|
|
# print detected device
|
|
print('Detected Part#: ' + device.part_number)
|
|
print('Detected Revision: ' + device.revision)
|
|
partDescription = getPartDescription(device.part_number)
|
|
# load configuration from detected device
|
|
load_device_config(partDescription, device.revision)
|
|
# check the default Part#/Rev in tools-config and offer to switch
|
|
checkTargetWithSelection(partDescription, device.revision,
|
|
selectedDescription, selectedRevision)
|
|
|
|
# update params from either selected part (B2) or detected part (B3/B4, etc)
|
|
DEVICE_PART_NUMBER = utils.config.DEVICE_PART_NUMBER
|
|
DEVICE_REVISION = utils.config.DEVICE_REVISION
|
|
DEVICE_PACKAGE = utils.config.DEVICE_PACKAGE
|
|
DEVICE_REV_PACKAGE_EXT = utils.config.DEVICE_REV_PACKAGE_EXT
|
|
DEVICE_OFFSET = utils.config.DEVICE_OFFSET
|
|
MRAM_BASE_ADDRESS = utils.config.MRAM_BASE_ADDRESS
|
|
ALIF_BASE_ADDRESS = utils.config.ALIF_BASE_ADDRESS
|
|
MRAM_SIZE = utils.config.MRAM_SIZE
|
|
HASHES_DB = utils.config.HASHES_DB
|
|
|
|
if device.revision == 'B2':
|
|
if device.revision != DEVICE_REVISION:
|
|
print("[ERROR] Target device revision (%s) mismatch with configured device (%s)"
|
|
% (device.revision,DEVICE_REVISION))
|
|
sys.exit(EXIT_WITH_ERROR)
|
|
|
|
env_ext = ''
|
|
if device.env.lower() in HASHES_DB:
|
|
if HASHES_DB[device.env] == 'DEV':
|
|
env_ext = '-dev'
|
|
|
|
# for devices in CM LCS, we use the DEV package
|
|
if device.env == '00000000000000000000000000000000':
|
|
print('Device is not provisioned!')
|
|
env_ext = '-dev'
|
|
|
|
# Start the recovery process
|
|
print('[INFO] System TOC Recovery with parameters:')
|
|
print('- Device Part# ' + DEVICE_PART_NUMBER + ' - Rev: ' + DEVICE_REVISION)
|
|
print('- MRAM Base Address: ' + hex(ALIF_BASE_ADDRESS))
|
|
|
|
argList = ''
|
|
action = 'Burning: '
|
|
|
|
rev_ext = DEVICE_REV_PACKAGE_EXT[DEVICE_REVISION]
|
|
alif_image = 'alif/' + DEVICE_PACKAGE + '-' + rev_ext + env_ext + '.bin'
|
|
alif_offset = 'alif/' + DEVICE_OFFSET + '-' + rev_ext + env_ext + '.bin'
|
|
|
|
# check images exist...
|
|
if not os.path.exists(alif_image):
|
|
print('Image ' + alif_image + ' does not exist!')
|
|
sys.exit(EXIT_WITH_ERROR)
|
|
|
|
if not os.path.exists(alif_offset):
|
|
print('Image ' + alif_offset + ' does not exist!')
|
|
sys.exit(EXIT_WITH_ERROR)
|
|
|
|
argList = '../' + alif_image + ' ' + hex(ALIF_BASE_ADDRESS) + \
|
|
' ../' + alif_offset + ' ' + hex(MRAM_BASE_ADDRESS + MRAM_SIZE - 16)
|
|
|
|
# validate all parameters
|
|
#argList = validateArgList(action, argList.strip())
|
|
if sys.platform == "linux" or sys.platform == "darwin":
|
|
argList = argList.replace('../','')
|
|
else:
|
|
argList = argList.replace('/','\\')
|
|
|
|
items = argList.split(' ')
|
|
|
|
for e in range(1, len(items),2):
|
|
addr = items[e]
|
|
fileName = items[e-1]
|
|
fileName = fileName.replace('..\\','')
|
|
|
|
write_mram(isp, fileName, addr, False)
|
|
|
|
def recovery_action(isp):
|
|
"""
|
|
Recover MRAM via SEROM. Reset the device at the end.
|
|
"""
|
|
|
|
recovery_action_no_reset(isp)
|
|
|
|
print("[INFO] Target reset")
|
|
isp_reset(isp) # Reset the target
|