obdata.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #!/usr/bin/env python3
  2. from enum import Enum
  3. from dataclasses import dataclass
  4. from typing import Tuple
  5. from array import array
  6. class OBException(ValueError):
  7. pass
  8. @dataclass
  9. class OBParams:
  10. word_idx: int
  11. bits: Tuple[int, int]
  12. name: str
  13. _OBS_descr = (
  14. OBParams(0, (0, 8), "RDP"),
  15. OBParams(0, (8, 9), "ESE"),
  16. OBParams(0, (9, 12), "BOR_LEV"),
  17. OBParams(0, (12, 13), "nRST_STOP"),
  18. OBParams(0, (13, 14), "nRST_STDBY"),
  19. OBParams(0, (14, 15), "nRSTSHDW"),
  20. OBParams(0, (15, 16), "UNUSED1"),
  21. OBParams(0, (16, 17), "IWDGSW"),
  22. OBParams(0, (17, 18), "IWDGSTOP"),
  23. OBParams(0, (18, 19), "IWGDSTDBY"), # ST's typo: IWDGSTDBY
  24. OBParams(0, (18, 19), "IWDGSTDBY"), # ST's typo: IWDGSTDBY
  25. OBParams(0, (19, 20), "WWDGSW"),
  26. OBParams(0, (20, 23), "UNUSED2"),
  27. OBParams(0, (23, 24), "nBOOT1"),
  28. OBParams(0, (24, 25), "SRAM2PE"),
  29. OBParams(0, (25, 26), "SRAM2RST"),
  30. OBParams(0, (26, 27), "nSWBOOT0"),
  31. OBParams(0, (27, 28), "nBOOT0"),
  32. OBParams(0, (28, 29), "UNUSED3"),
  33. OBParams(0, (29, 32), "AGC_TRIM"),
  34. OBParams(1, (0, 9), "PCROP1A_STRT"),
  35. OBParams(1, (9, 32), "UNUSED"),
  36. OBParams(2, (0, 9), "PCROP1A_END"),
  37. OBParams(2, (9, 31), "UNUSED"),
  38. OBParams(2, (31, 32), "PCROP_RDP"),
  39. OBParams(3, (0, 8), "WRP1A_STRT"),
  40. OBParams(3, (8, 16), "UNUSED1"),
  41. OBParams(3, (16, 24), "WRP1A_END"),
  42. OBParams(3, (24, 32), "UNUSED2"),
  43. OBParams(4, (0, 8), "WRP1B_STRT"),
  44. OBParams(4, (8, 16), "UNUSED1"),
  45. OBParams(4, (16, 24), "WRP1B_END"),
  46. OBParams(4, (24, 32), "UNUSED2"),
  47. OBParams(5, (0, 9), "PCROP1B_STRT"),
  48. OBParams(5, (9, 32), "UNUSED"),
  49. OBParams(6, (0, 9), "PCROP1B_END"),
  50. OBParams(6, (9, 32), "UNUSED"),
  51. OBParams(13, (0, 14), "IPCCDBA"),
  52. OBParams(13, (14, 32), "UNUSED"),
  53. OBParams(14, (0, 8), "SFSA"),
  54. OBParams(14, (8, 9), "FSD"),
  55. OBParams(14, (9, 12), "UNUSED1"),
  56. OBParams(14, (12, 13), "DDS"),
  57. OBParams(14, (13, 32), "UNUSED2"),
  58. OBParams(15, (0, 18), "SBRV"),
  59. OBParams(15, (18, 23), "SBRSA"),
  60. OBParams(15, (23, 24), "BRSD"),
  61. OBParams(15, (24, 25), "UNUSED1"),
  62. OBParams(15, (25, 30), "SNBRSA"),
  63. OBParams(15, (30, 31), "NBRSD"),
  64. OBParams(15, (31, 32), "C2OPT"),
  65. )
  66. _OBS = dict((param.name, param) for param in _OBS_descr)
  67. @dataclass
  68. class EncodedOBValue:
  69. value: int
  70. mask: int
  71. params: OBParams
  72. class OptionByte:
  73. class OBMode(Enum):
  74. IGNORE = 0
  75. READ = 1
  76. READ_WRITE = 2
  77. @classmethod
  78. def from_str(cls, value):
  79. if value == "r":
  80. return cls.READ
  81. elif value == "rw":
  82. return cls.READ_WRITE
  83. else:
  84. raise OBException(f"Unknown OB check mode '{value}'")
  85. def __init__(self, obstr):
  86. parts = obstr.split(":")
  87. if len(parts) != 3:
  88. raise OBException(f"Invalid OB value definition {obstr}")
  89. self.name = parts[0]
  90. self.value = int(parts[1], 16)
  91. self.mode = OptionByte.OBMode.from_str(parts[2].strip())
  92. self.descr = _OBS.get(self.name, None)
  93. if self.descr is None:
  94. raise OBException(f"Missing OB descriptor for {self.name}")
  95. def encode(self):
  96. startbit, endbit = self.descr.bits
  97. value_mask = 2 ** (endbit - startbit) - 1
  98. value_corrected = self.value & value_mask
  99. value_shifted = value_corrected << startbit
  100. value_mask_shifted = value_mask << startbit
  101. return EncodedOBValue(value_shifted, value_mask_shifted, self)
  102. def __repr__(self):
  103. return f"<OB {self.name}, 0x{self.value:x}, {self.mode} at 0x{id(self):X}>"
  104. @dataclass
  105. class ObReferenceValues:
  106. reference: bytes
  107. compare_mask: bytes
  108. write_mask: bytes
  109. class ObReferenceValuesGenerator:
  110. def __init__(self):
  111. self.compare_mask = array("I", [0] * 16)
  112. self.write_mask = array("I", [0] * 16)
  113. self.ref_values = array("I", [0] * 16)
  114. def __repr__(self):
  115. return (
  116. f"<OBRefs REFS=[{' '.join(hex(v) for v in self.ref_values)}] "
  117. f"CMPMASK=[{' '.join(hex(v) for v in self.compare_mask)}] "
  118. f"WRMASK=[{' '.join(hex(v) for v in self.write_mask)}] "
  119. )
  120. def export_values(self):
  121. export_cmpmask = array("I")
  122. for value in self.compare_mask:
  123. export_cmpmask.append(value)
  124. export_cmpmask.append(value)
  125. export_wrmask = array("I")
  126. for value in self.write_mask:
  127. export_wrmask.append(value)
  128. export_wrmask.append(value)
  129. export_refvals = array("I")
  130. for cmpmask, refval in zip(self.compare_mask, self.ref_values):
  131. export_refvals.append(refval)
  132. export_refvals.append((refval ^ 0xFFFFFFFF) & cmpmask)
  133. return export_refvals, export_cmpmask, export_wrmask
  134. def export(self):
  135. return ObReferenceValues(*map(lambda a: a.tobytes(), self.export_values()))
  136. def apply(self, ob):
  137. ob_params = ob.descr
  138. encoded_ob = ob.encode()
  139. self.compare_mask[ob_params.word_idx] |= encoded_ob.mask
  140. self.ref_values[ob_params.word_idx] |= encoded_ob.value
  141. if ob.mode == OptionByte.OBMode.READ_WRITE:
  142. self.write_mask[ob_params.word_idx] |= encoded_ob.mask
  143. class OptionBytesData:
  144. def __init__(self, obfname):
  145. self.obs = list()
  146. with open(obfname, "rt") as obfin:
  147. self.obs = list(
  148. OptionByte(line) for line in obfin if not line.startswith("#")
  149. )
  150. def gen_values(self):
  151. obref = ObReferenceValuesGenerator()
  152. list(obref.apply(ob) for ob in self.obs)
  153. return obref
  154. def main():
  155. with open("../../../../logs/obs.bin", "rb") as obsbin:
  156. ob_sample = obsbin.read(128)
  157. ob_sample_arr = array("I", ob_sample)
  158. print(ob_sample_arr)
  159. obd = OptionBytesData("../../ob.data")
  160. print(obd.obs)
  161. # print(obd.gen_values().export())
  162. ref, mask, wrmask = obd.gen_values().export_values()
  163. for idx in range(len(ob_sample_arr)):
  164. real_masked = ob_sample_arr[idx] & mask[idx]
  165. print(
  166. f"#{idx}: ref {ref[idx]:08x} real {real_masked:08x} ({ob_sample_arr[idx]:08x} & {mask[idx]:08x}) match {ref[idx]==real_masked}"
  167. )
  168. # print(ob_sample)
  169. if __name__ == "__main__":
  170. main()