flipperzero-firmware/scripts/flipper/utils/register.py
Sergey Gavrilov 727f043747
OpenOCD scripts (#2101)
* Scripts: option bytes check
* Scripts: option bytes set
* Scripts: openocd config
* Scripts: increased readability, process IPCCBR option byte
* Scripts: split dap_ob.py
* Updater: process IPCCBR option byte
* Scripts: move chip-related functions to chip definition
* Scripts: freeze CPU registers
* Scripts: flash programming routine
* ob.py
* otp.py
* otp: handle errors correctly
* downgrade to python 3.9
* correct type hinting
* Scripts: fix path to ob.data

Co-authored-by: あく <alleteam@gmail.com>
2022-12-27 21:59:36 +09:00

96 lines
3.0 KiB
Python

from dataclasses import dataclass
from flipper.utils.openocd import OpenOCD
@dataclass
class RegisterBitDefinition:
name: str
offset: int
size: int
value: int = 0
class Register32:
def __init__(self, address: int, definition_list: list[RegisterBitDefinition]):
self.__dict__["names"] = [definition.name for definition in definition_list]
self.names = [definition.name for definition in definition_list] # typecheck
self.address = address
self.definition_list = definition_list
# Validate that the definitions are not overlapping
for i in range(len(definition_list)):
for j in range(i + 1, len(definition_list)):
if self._is_overlapping(definition_list[i], definition_list[j]):
raise ValueError("Register definitions are overlapping")
self.freezed = True
def _is_overlapping(
self, a: RegisterBitDefinition, b: RegisterBitDefinition
) -> bool:
if a.offset + a.size <= b.offset:
return False
if b.offset + b.size <= a.offset:
return False
return True
def _get_definition(self, name: str) -> RegisterBitDefinition:
for definition in self.definition_list:
if definition.name == name:
return definition
raise ValueError(f"Register definition '{name}' not found")
def get_definition_list(self) -> list[RegisterBitDefinition]:
return self.definition_list
def get_address(self) -> int:
return self.address
def set_reg_value(self, name: str, value: int):
definition = self._get_definition(name)
if value > (1 << definition.size) - 1:
raise ValueError(
f"Value {value} is too large for register definition '{name}'"
)
definition.value = value
def get_reg_value(self, name: str) -> int:
definition = self._get_definition(name)
return definition.value
def __getattr__(self, attr):
if str(attr) in self.names:
return self.get_reg_value(str(attr))
else:
return self.__dict__[attr]
def __setattr__(self, attr, value):
if str(attr) in self.names:
self.set_reg_value(str(attr), value)
else:
if attr in self.__dict__ or "freezed" not in self.__dict__:
self.__dict__[attr] = value
else:
raise AttributeError(f"Attribute '{attr}' not found")
def __dir__(self):
return self.names
def set(self, value: int):
for definition in self.definition_list:
definition.value = (value >> definition.offset) & (
(1 << definition.size) - 1
)
def get(self) -> int:
value = 0
for definition in self.definition_list:
value |= definition.value << definition.offset
return value
def load(self, openocd: OpenOCD):
self.set(openocd.read_32(self.address))
def store(self, openocd: OpenOCD):
openocd.write_32(self.address, self.get())