[FL-3180] OTP programmer: return exit code based on error type (#2504)
This commit is contained in:
		
							parent
							
								
									7de7fa293b
								
							
						
					
					
						commit
						6ec62f48f9
					
				| @ -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 | ||||||
|  |         ) | ||||||
|  | |||||||
| @ -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) | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Sergey Gavrilov
						Sergey Gavrilov