stm32wb55.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. import logging
  2. from enum import Enum
  3. from flipper.utils.openocd import OpenOCD
  4. from flipper.utils.register import Register32, RegisterBitDefinition
  5. class STM32WB55:
  6. # Address of OTP memory in flash
  7. OTP_BASE = 0x1FFF7000
  8. # Address of Option byte in flash
  9. OPTION_BYTE_BASE = 0x1FFF8000
  10. # Flash base address
  11. FLASH_BASE = 0x58004000
  12. # Flash unlock register
  13. FLASH_KEYR = FLASH_BASE + 0x08
  14. # Option byte unlock register
  15. FLASH_OPTKEYR = FLASH_BASE + 0x0C
  16. # Flash unlock keys
  17. FLASH_UNLOCK_KEY1 = 0x45670123
  18. FLASH_UNLOCK_KEY2 = 0xCDEF89AB
  19. # Option byte unlock keys
  20. FLASH_UNLOCK_OPTKEY1 = 0x08192A3B
  21. FLASH_UNLOCK_OPTKEY2 = 0x4C5D6E7F
  22. # Flash control register
  23. FLASH_CR = Register32(
  24. FLASH_BASE + 0x14,
  25. [
  26. RegisterBitDefinition("PG", 0, 1),
  27. RegisterBitDefinition("PER", 1, 1),
  28. RegisterBitDefinition("MER", 2, 1),
  29. RegisterBitDefinition("PNB", 3, 8),
  30. RegisterBitDefinition("_", 11, 5),
  31. RegisterBitDefinition("STRT", 16, 1),
  32. RegisterBitDefinition("OPT_STRT", 17, 1),
  33. RegisterBitDefinition("FSTPG", 18, 1),
  34. RegisterBitDefinition("_", 19, 5),
  35. RegisterBitDefinition("EOPIE", 24, 1),
  36. RegisterBitDefinition("ERRIE", 25, 1),
  37. RegisterBitDefinition("RD_ERRIE", 26, 1),
  38. RegisterBitDefinition("OBL_LAUNCH", 27, 1),
  39. RegisterBitDefinition("_", 28, 2),
  40. RegisterBitDefinition("OPT_LOCK", 30, 1),
  41. RegisterBitDefinition("LOCK", 31, 1),
  42. ],
  43. )
  44. # Flash status register
  45. FLASH_SR = Register32(
  46. FLASH_BASE + 0x10,
  47. [
  48. RegisterBitDefinition("EOP", 0, 1),
  49. RegisterBitDefinition("OP_ERR", 1, 1),
  50. RegisterBitDefinition("_", 2, 1),
  51. RegisterBitDefinition("PROG_ERR", 3, 1),
  52. RegisterBitDefinition("WRP_ERR", 4, 1),
  53. RegisterBitDefinition("PGA_ERR", 5, 1),
  54. RegisterBitDefinition("SIZE_ERR", 6, 1),
  55. RegisterBitDefinition("PGS_ERR", 7, 1),
  56. RegisterBitDefinition("MISS_ERR", 8, 1),
  57. RegisterBitDefinition("FAST_ERR", 9, 1),
  58. RegisterBitDefinition("_", 10, 3),
  59. RegisterBitDefinition("OPTNV", 13, 1),
  60. RegisterBitDefinition("RD_ERR", 14, 1),
  61. RegisterBitDefinition("OPTV_ERR", 15, 1),
  62. RegisterBitDefinition("BSY", 16, 1),
  63. RegisterBitDefinition("_", 17, 1),
  64. RegisterBitDefinition("CFGBSY", 18, 1),
  65. RegisterBitDefinition("PESD", 19, 1),
  66. RegisterBitDefinition("_", 20, 12),
  67. ],
  68. )
  69. # Option byte registers
  70. FLASH_OPTR = FLASH_BASE + 0x20
  71. FLASH_PCROP1ASR = FLASH_BASE + 0x24
  72. FLASH_PCROP1AER = FLASH_BASE + 0x28
  73. FLASH_WRP1AR = FLASH_BASE + 0x2C
  74. FLASH_WRP1BR = FLASH_BASE + 0x30
  75. FLASH_PCROP1BSR = FLASH_BASE + 0x34
  76. FLASH_PCROP1BER = FLASH_BASE + 0x38
  77. FLASH_IPCCBR = FLASH_BASE + 0x3C
  78. # Map option byte dword index to register address
  79. OPTION_BYTE_MAP_TO_REGS = {
  80. 0: FLASH_OPTR,
  81. 1: FLASH_PCROP1ASR,
  82. 2: FLASH_PCROP1AER,
  83. 3: FLASH_WRP1AR,
  84. 4: FLASH_WRP1BR,
  85. 5: FLASH_PCROP1BSR,
  86. 6: FLASH_PCROP1BER,
  87. 7: None, # Invalid Options
  88. 8: None, # Invalid Options
  89. 9: None, # Invalid Options
  90. 10: None, # Invalid Options
  91. 11: None, # Invalid Options
  92. 12: None, # Invalid Options
  93. 13: FLASH_IPCCBR,
  94. 14: None, # Secure Flash
  95. 15: None, # Core 2 Options
  96. }
  97. def __init__(self):
  98. self.logger = logging.getLogger("STM32WB55")
  99. class RunMode(Enum):
  100. Init = "init"
  101. Run = "run"
  102. Halt = "halt"
  103. def reset(self, oocd: OpenOCD, mode: RunMode):
  104. self.logger.debug("Resetting device")
  105. oocd.send_tcl(f"reset {mode.value}")
  106. def clear_flash_errors(self, oocd: OpenOCD):
  107. # Errata 2.2.9: Flash OPTVERR flag is always set after system reset
  108. # And also clear all other flash error flags
  109. self.logger.debug("Resetting flash errors")
  110. self.FLASH_SR.load(oocd)
  111. self.FLASH_SR.OP_ERR = 1
  112. self.FLASH_SR.PROG_ERR = 1
  113. self.FLASH_SR.WRP_ERR = 1
  114. self.FLASH_SR.PGA_ERR = 1
  115. self.FLASH_SR.SIZE_ERR = 1
  116. self.FLASH_SR.PGS_ERR = 1
  117. self.FLASH_SR.MISS_ERR = 1
  118. self.FLASH_SR.FAST_ERR = 1
  119. self.FLASH_SR.RD_ERR = 1
  120. self.FLASH_SR.OPTV_ERR = 1
  121. self.FLASH_SR.store(oocd)
  122. def flash_unlock(self, oocd: OpenOCD):
  123. # Check if flash is already unlocked
  124. self.FLASH_CR.load(oocd)
  125. if self.FLASH_CR.LOCK == 0:
  126. self.logger.debug("Flash is already unlocked")
  127. return
  128. # Unlock flash
  129. self.logger.debug("Unlocking Flash")
  130. oocd.write_32(self.FLASH_KEYR, self.FLASH_UNLOCK_KEY1)
  131. oocd.write_32(self.FLASH_KEYR, self.FLASH_UNLOCK_KEY2)
  132. # Check if flash is unlocked
  133. self.FLASH_CR.load(oocd)
  134. if self.FLASH_CR.LOCK == 0:
  135. self.logger.debug("Flash unlocked")
  136. else:
  137. self.logger.error("Flash unlock failed")
  138. raise Exception("Flash unlock failed")
  139. def option_bytes_unlock(self, oocd: OpenOCD):
  140. # Check if options is already unlocked
  141. self.FLASH_CR.load(oocd)
  142. if self.FLASH_CR.OPT_LOCK == 0:
  143. self.logger.debug("Options is already unlocked")
  144. return
  145. # Unlock options
  146. self.logger.debug("Unlocking Options")
  147. oocd.write_32(self.FLASH_OPTKEYR, self.FLASH_UNLOCK_OPTKEY1)
  148. oocd.write_32(self.FLASH_OPTKEYR, self.FLASH_UNLOCK_OPTKEY2)
  149. # Check if options is unlocked
  150. self.FLASH_CR.load(oocd)
  151. if self.FLASH_CR.OPT_LOCK == 0:
  152. self.logger.debug("Options unlocked")
  153. else:
  154. self.logger.error("Options unlock failed")
  155. raise Exception("Options unlock failed")
  156. def option_bytes_lock(self, oocd: OpenOCD):
  157. # Check if options is already locked
  158. self.FLASH_CR.load(oocd)
  159. if self.FLASH_CR.OPT_LOCK == 1:
  160. self.logger.debug("Options is already locked")
  161. return
  162. # Lock options
  163. self.logger.debug("Locking Options")
  164. self.FLASH_CR.OPT_LOCK = 1
  165. self.FLASH_CR.store(oocd)
  166. # Check if options is locked
  167. self.FLASH_CR.load(oocd)
  168. if self.FLASH_CR.OPT_LOCK == 1:
  169. self.logger.debug("Options locked")
  170. else:
  171. self.logger.error("Options lock failed")
  172. raise Exception("Options lock failed")
  173. def flash_lock(self, oocd: OpenOCD):
  174. # Check if flash is already locked
  175. self.FLASH_CR.load(oocd)
  176. if self.FLASH_CR.LOCK == 1:
  177. self.logger.debug("Flash is already locked")
  178. return
  179. # Lock flash
  180. self.logger.debug("Locking Flash")
  181. self.FLASH_CR.LOCK = 1
  182. self.FLASH_CR.store(oocd)
  183. # Check if flash is locked
  184. self.FLASH_CR.load(oocd)
  185. if self.FLASH_CR.LOCK == 1:
  186. self.logger.debug("Flash locked")
  187. else:
  188. self.logger.error("Flash lock failed")
  189. raise Exception("Flash lock failed")
  190. def option_bytes_apply(self, oocd: OpenOCD):
  191. self.logger.debug("Applying Option Bytes")
  192. self.FLASH_CR.load(oocd)
  193. self.FLASH_CR.OPT_STRT = 1
  194. self.FLASH_CR.store(oocd)
  195. # Wait for Option Bytes to be applied
  196. self.flash_wait_for_operation(oocd)
  197. def option_bytes_load(self, oocd: OpenOCD):
  198. self.logger.debug("Loading Option Bytes")
  199. self.FLASH_CR.load(oocd)
  200. self.FLASH_CR.OBL_LAUNCH = 1
  201. self.FLASH_CR.store(oocd)
  202. def option_bytes_id_to_address(self, id: int) -> int:
  203. # Check if this option byte (dword) is mapped to a register
  204. device_reg_addr = self.OPTION_BYTE_MAP_TO_REGS.get(id, None)
  205. if device_reg_addr is None:
  206. raise Exception(f"Option Byte {id} is not mapped to a register")
  207. return device_reg_addr
  208. def flash_wait_for_operation(self, oocd: OpenOCD):
  209. # Wait for flash operation to complete
  210. # TODO: timeout
  211. while True:
  212. self.FLASH_SR.load(oocd)
  213. if self.FLASH_SR.BSY == 0:
  214. break
  215. def flash_dump_status_register(self, oocd: OpenOCD):
  216. self.FLASH_SR.load(oocd)
  217. self.logger.info(f"FLASH_SR: {self.FLASH_SR.get():08x}")
  218. if self.FLASH_SR.EOP:
  219. self.logger.info(" End of operation")
  220. if self.FLASH_SR.OP_ERR:
  221. self.logger.error(" Operation error")
  222. if self.FLASH_SR.PROG_ERR:
  223. self.logger.error(" Programming error")
  224. if self.FLASH_SR.WRP_ERR:
  225. self.logger.error(" Write protection error")
  226. if self.FLASH_SR.PGA_ERR:
  227. self.logger.error(" Programming alignment error")
  228. if self.FLASH_SR.SIZE_ERR:
  229. self.logger.error(" Size error")
  230. if self.FLASH_SR.PGS_ERR:
  231. self.logger.error(" Programming sequence error")
  232. if self.FLASH_SR.MISS_ERR:
  233. self.logger.error(" Fast programming data miss error")
  234. if self.FLASH_SR.FAST_ERR:
  235. self.logger.error(" Fast programming error")
  236. if self.FLASH_SR.OPTNV:
  237. self.logger.info(" User option OPTVAL indication")
  238. if self.FLASH_SR.RD_ERR:
  239. self.logger.info(" PCROP read error")
  240. if self.FLASH_SR.OPTV_ERR:
  241. self.logger.info(" Option and Engineering bits loading validity error")
  242. if self.FLASH_SR.BSY:
  243. self.logger.info(" Busy")
  244. if self.FLASH_SR.CFGBSY:
  245. self.logger.info(" Programming or erase configuration busy")
  246. if self.FLASH_SR.PESD:
  247. self.logger.info(" Programming / erase operation suspended.")
  248. def write_flash_64(self, oocd: OpenOCD, address: int, word_1: int, word_2: int):
  249. self.logger.debug(f"Writing flash at address {address:08x}")
  250. if address % 8 != 0:
  251. self.logger.error("Address must be aligned to 8 bytes")
  252. raise Exception("Address must be aligned to 8 bytes")
  253. if word_1 == oocd.read_32(address) and word_2 == oocd.read_32(address + 4):
  254. self.logger.debug("Data is already programmed")
  255. return
  256. self.flash_unlock(oocd)
  257. # Check that no flash main memory operation is ongoing by checking the BSY bit
  258. self.FLASH_SR.load(oocd)
  259. if self.FLASH_SR.BSY:
  260. self.logger.error("Flash is busy")
  261. self.flash_dump_status_register(oocd)
  262. raise Exception("Flash is busy")
  263. # Enable end of operation interrupts and error interrupts
  264. self.FLASH_CR.load(oocd)
  265. self.FLASH_CR.EOPIE = 1
  266. self.FLASH_CR.ERRIE = 1
  267. self.FLASH_CR.store(oocd)
  268. # Check that flash memory program and erase operations are allowed
  269. if self.FLASH_SR.PESD:
  270. self.logger.error("Flash operations are not allowed")
  271. self.flash_dump_status_register(oocd)
  272. raise Exception("Flash operations are not allowed")
  273. # Check and clear all error programming flags due to a previous programming.
  274. self.clear_flash_errors(oocd)
  275. # Set the PG bit in the Flash memory control register (FLASH_CR)
  276. self.FLASH_CR.load(oocd)
  277. self.FLASH_CR.PG = 1
  278. self.FLASH_CR.store(oocd)
  279. # Perform the data write operation at the desired memory address, only double word (64 bits) can be programmed.
  280. # Write the first word
  281. oocd.send_tcl(f"mww 0x{address:08x} 0x{word_1:08x}")
  282. # Write the second word
  283. oocd.send_tcl(f"mww 0x{(address + 4):08x} 0x{word_2:08x}")
  284. # Wait for the BSY bit to be cleared
  285. self.flash_wait_for_operation(oocd)
  286. # Check that EOP flag is set in the FLASH_SR register
  287. self.FLASH_SR.load(oocd)
  288. if not self.FLASH_SR.EOP:
  289. self.logger.error("Flash operation failed")
  290. self.flash_dump_status_register(oocd)
  291. raise Exception("Flash operation failed")
  292. # Clear the EOP flag
  293. self.FLASH_SR.load(oocd)
  294. self.FLASH_SR.EOP = 1
  295. self.FLASH_SR.store(oocd)
  296. # Clear the PG bit in the FLASH_CR register
  297. self.FLASH_CR.load(oocd)
  298. self.FLASH_CR.PG = 0
  299. self.FLASH_CR.store(oocd)
  300. self.flash_lock(oocd)