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>
This commit is contained in:
95
scripts/flipper/utils/register.py
Normal file
95
scripts/flipper/utils/register.py
Normal file
@@ -0,0 +1,95 @@
|
||||
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())
|
||||
Reference in New Issue
Block a user