[FL-3180] OTP programmer: return exit code based on error type (#2504)

This commit is contained in:
Sergey Gavrilov 2023-03-20 05:07:17 -07:00 committed by GitHub
parent 7de7fa293b
commit 6ec62f48f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 21 deletions

View File

@ -1,6 +1,7 @@
import logging import logging
import os import os
import typing import typing
from enum import Enum
from flipper.utils.programmer import Programmer from flipper.utils.programmer import Programmer
from flipper.utils.openocd import OpenOCD from flipper.utils.openocd import OpenOCD
@ -8,6 +9,14 @@ from flipper.utils.stm32wb55 import STM32WB55
from flipper.assets.obdata import OptionBytesData from flipper.assets.obdata import OptionBytesData
class OpenOCDProgrammerResult(Enum):
Success = 0
ErrorGeneric = 1
ErrorAlignment = 2
ErrorAlreadyWritten = 3
ErrorValidation = 4
class OpenOCDProgrammer(Programmer): class OpenOCDProgrammer(Programmer):
def __init__( def __init__(
self, self,
@ -199,18 +208,18 @@ class OpenOCDProgrammer(Programmer):
return True return True
def otp_write(self, address: int, file_path: str) -> bool: def otp_write(self, address: int, file_path: str) -> OpenOCDProgrammerResult:
# Open file, check that it aligned to 8 bytes # Open file, check that it aligned to 8 bytes
with open(file_path, "rb") as f: with open(file_path, "rb") as f:
data = f.read() data = f.read()
if len(data) % 8 != 0: if len(data) % 8 != 0:
self.logger.error(f"File {file_path} is not aligned to 8 bytes") self.logger.error(f"File {file_path} is not aligned to 8 bytes")
return False return OpenOCDProgrammerResult.ErrorAlignment
# Check that address is aligned to 8 bytes # Check that address is aligned to 8 bytes
if address % 8 != 0: if address % 8 != 0:
self.logger.error(f"Address {address} is not aligned to 8 bytes") self.logger.error(f"Address {address} is not aligned to 8 bytes")
return False return OpenOCDProgrammerResult.ErrorAlignment
# Get size of data # Get size of data
data_size = len(data) data_size = len(data)
@ -218,7 +227,7 @@ class OpenOCDProgrammer(Programmer):
# Check that data size is aligned to 8 bytes # Check that data size is aligned to 8 bytes
if data_size % 8 != 0: if data_size % 8 != 0:
self.logger.error(f"Data size {data_size} is not aligned to 8 bytes") self.logger.error(f"Data size {data_size} is not aligned to 8 bytes")
return False return OpenOCDProgrammerResult.ErrorAlignment
self.logger.debug(f"Writing {data_size} bytes to OTP at {address:08X}") self.logger.debug(f"Writing {data_size} bytes to OTP at {address:08X}")
self.logger.debug(f"Data: {data.hex().upper()}") self.logger.debug(f"Data: {data.hex().upper()}")
@ -241,14 +250,14 @@ class OpenOCDProgrammer(Programmer):
self.logger.error( self.logger.error(
f"OTP memory at {address + i:08X} is not empty: {device_word:08X}" f"OTP memory at {address + i:08X} is not empty: {device_word:08X}"
) )
raise Exception("OTP memory is not empty") return OpenOCDProgrammerResult.ErrorAlreadyWritten
if device_word != file_word: if device_word != file_word:
already_written = False already_written = False
if already_written: if already_written:
self.logger.info(f"OTP memory is already written with the given data") self.logger.info(f"OTP memory is already written with the given data")
return True return OpenOCDProgrammerResult.Success
self.reset(self.RunMode.Stop) self.reset(self.RunMode.Stop)
stm32.clear_flash_errors(oocd) stm32.clear_flash_errors(oocd)
@ -278,4 +287,8 @@ class OpenOCDProgrammer(Programmer):
stm32.reset(oocd, stm32.RunMode.Run) stm32.reset(oocd, stm32.RunMode.Run)
oocd.stop() oocd.stop()
return validation_result return (
OpenOCDProgrammerResult.Success
if validation_result
else OpenOCDProgrammerResult.ErrorValidation
)

View File

@ -34,8 +34,16 @@ OTP_DISPLAYS = {
} }
from flipper.app import App from flipper.app import App
from flipper.cube import CubeProgrammer from flipper.utils.programmer_openocd import OpenOCDProgrammer, OpenOCDProgrammerResult
from flipper.utils.programmer_openocd import OpenOCDProgrammer
class OTPException(Exception):
def __init__(self, message: str, result: OpenOCDProgrammerResult):
self.message = message
self.result = result
def get_exit_code(self) -> int:
return int(self.result.value)
class Main(App): class Main(App):
@ -183,13 +191,14 @@ class Main(App):
self.args.serial, self.args.serial,
) )
if not openocd.otp_write(0x1FFF7000, filename): programmer_result = openocd.otp_write(0x1FFF7000, filename)
raise Exception("Failed to flash OTP") if programmer_result != OpenOCDProgrammerResult.Success:
raise OTPException("Failed to flash OTP", programmer_result)
self.logger.info(f"Flashed Successfully") self.logger.info(f"Flashed Successfully")
except Exception as e: except OTPException as e:
self.logger.exception(e) self.logger.exception(e)
return 1 return e.get_exit_code()
finally: finally:
os.remove(filename) os.remove(filename)
@ -215,13 +224,14 @@ class Main(App):
self.args.serial, self.args.serial,
) )
if not openocd.otp_write(0x1FFF7010, filename): programmer_result = openocd.otp_write(0x1FFF7010, filename)
raise Exception("Failed to flash OTP") if programmer_result != OpenOCDProgrammerResult.Success:
raise OTPException("Failed to flash OTP", programmer_result)
self.logger.info(f"Flashed Successfully") self.logger.info(f"Flashed Successfully")
except Exception as e: except OTPException as e:
self.logger.exception(e) self.logger.exception(e)
return 1 return e.get_exit_code()
finally: finally:
os.remove(filename) os.remove(filename)
@ -249,13 +259,14 @@ class Main(App):
self.args.serial, self.args.serial,
) )
if not openocd.otp_write(0x1FFF7000, filename): programmer_result = openocd.otp_write(0x1FFF7000, filename)
raise Exception("Failed to flash OTP") if programmer_result != OpenOCDProgrammerResult.Success:
raise OTPException("Failed to flash OTP", programmer_result)
self.logger.info(f"Flashed Successfully") self.logger.info(f"Flashed Successfully")
except Exception as e: except OTPException as e:
self.logger.exception(e) self.logger.exception(e)
return 1 return e.get_exit_code()
finally: finally:
os.remove(filename) os.remove(filename)