register.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. from dataclasses import dataclass
  2. from flipper.utils.openocd import OpenOCD
  3. @dataclass
  4. class RegisterBitDefinition:
  5. name: str
  6. offset: int
  7. size: int
  8. value: int = 0
  9. class Register32:
  10. def __init__(self, address: int, definition_list: list[RegisterBitDefinition]):
  11. self.__dict__["names"] = [definition.name for definition in definition_list]
  12. self.names = [definition.name for definition in definition_list] # typecheck
  13. self.address = address
  14. self.definition_list = definition_list
  15. # Validate that the definitions are not overlapping
  16. for i in range(len(definition_list)):
  17. for j in range(i + 1, len(definition_list)):
  18. if self._is_overlapping(definition_list[i], definition_list[j]):
  19. raise ValueError("Register definitions are overlapping")
  20. self.freezed = True
  21. def _is_overlapping(
  22. self, a: RegisterBitDefinition, b: RegisterBitDefinition
  23. ) -> bool:
  24. if a.offset + a.size <= b.offset:
  25. return False
  26. if b.offset + b.size <= a.offset:
  27. return False
  28. return True
  29. def _get_definition(self, name: str) -> RegisterBitDefinition:
  30. for definition in self.definition_list:
  31. if definition.name == name:
  32. return definition
  33. raise ValueError(f"Register definition '{name}' not found")
  34. def get_definition_list(self) -> list[RegisterBitDefinition]:
  35. return self.definition_list
  36. def get_address(self) -> int:
  37. return self.address
  38. def set_reg_value(self, name: str, value: int):
  39. definition = self._get_definition(name)
  40. if value > (1 << definition.size) - 1:
  41. raise ValueError(
  42. f"Value {value} is too large for register definition '{name}'"
  43. )
  44. definition.value = value
  45. def get_reg_value(self, name: str) -> int:
  46. definition = self._get_definition(name)
  47. return definition.value
  48. def __getattr__(self, attr):
  49. if str(attr) in self.names:
  50. return self.get_reg_value(str(attr))
  51. else:
  52. return self.__dict__[attr]
  53. def __setattr__(self, attr, value):
  54. if str(attr) in self.names:
  55. self.set_reg_value(str(attr), value)
  56. else:
  57. if attr in self.__dict__ or "freezed" not in self.__dict__:
  58. self.__dict__[attr] = value
  59. else:
  60. raise AttributeError(f"Attribute '{attr}' not found")
  61. def __dir__(self):
  62. return self.names
  63. def set(self, value: int):
  64. for definition in self.definition_list:
  65. definition.value = (value >> definition.offset) & (
  66. (1 << definition.size) - 1
  67. )
  68. def get(self) -> int:
  69. value = 0
  70. for definition in self.definition_list:
  71. value |= definition.value << definition.offset
  72. return value
  73. def load(self, openocd: OpenOCD):
  74. self.set(openocd.read_32(self.address))
  75. def store(self, openocd: OpenOCD):
  76. openocd.write_32(self.address, self.get())