1
0

code-info-sync.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. const storageAccessProtocol = require('../../protocols/storage-access/index.js')
  2. const transport = require('../../transport/ble-core.js')
  3. const {
  4. createGroupsFromCodeInfo,
  5. parseCodeInfo
  6. } = require('../../domain/storage-access/code-info-parser.js')
  7. const {
  8. cloneImportedGroup,
  9. normalizeGroup
  10. } = require('../../domain/parameter-groups/model.js')
  11. const protocolIo = require('./protocol-io.js')
  12. function formatDwordHex(value) {
  13. const numberValue = Math.max(0, Math.floor(Number(value) || 0))
  14. return numberValue.toString(16).toUpperCase().padStart(8, '0')
  15. }
  16. function showCodeInfoError(label, message, options = {}) {
  17. if (options.showModal === false) return
  18. transport.showCommandAlert(label, message)
  19. }
  20. async function readCodeInfoBlock(label = '同步CodeInfo', kind = 'storage-code-info-read', options = {}) {
  21. const protocolIoOptions = protocolIo.normalizeProtocolIoOptions({
  22. ...options,
  23. useDeviceCaps: false
  24. })
  25. const descriptorBytes = await protocolIo.readMemory(
  26. storageAccessProtocol.AREA.CODEINFO,
  27. storageAccessProtocol.CODE_INFO_DESCRIPTOR_ADDRESS,
  28. storageAccessProtocol.CODE_INFO_DESCRIPTOR_BYTE_LENGTH,
  29. label,
  30. `${kind}-descriptor`,
  31. {
  32. ...protocolIoOptions,
  33. showModal: false,
  34. useDeviceCaps: false
  35. }
  36. )
  37. if (!descriptorBytes) {
  38. showCodeInfoError(label, 'CodeInfo 描述符读取失败或超时', protocolIoOptions)
  39. return null
  40. }
  41. let descriptor
  42. try {
  43. descriptor = storageAccessProtocol.parseCodeInfoDescriptorBytes(descriptorBytes)
  44. } catch (error) {
  45. showCodeInfoError(label, error.message || 'CodeInfo 描述符长度无效', protocolIoOptions)
  46. return null
  47. }
  48. let codeInfoAddressWidth
  49. try {
  50. codeInfoAddressWidth = storageAccessProtocol.normalizeDescriptorAddressWidth(
  51. descriptor.codeInfoAddressWidth
  52. )
  53. } catch (error) {
  54. showCodeInfoError(label, error.message || 'CodeInfo 描述符地址长度无效', protocolIoOptions)
  55. return null
  56. }
  57. const codeInfoAddress = Number(descriptor.codeInfoAddress || 0)
  58. const codeInfoByteLength = Number(descriptor.codeInfoByteLength || 0)
  59. const codeInfoMaxPacketLength = Number(descriptor.codeInfoMaxPacketLength || 0) & 0xFFFF
  60. const codeInfoMemoryEndian = String(descriptor.codeInfoMemoryEndian || 'big').trim()
  61. const codeInfoMemoryType = codeInfoAddressWidth === 32
  62. ? storageAccessProtocol.AREA.ADDR32
  63. : storageAccessProtocol.AREA.CODE
  64. const codeInfoReadAddress = codeInfoAddressWidth === 32 ? codeInfoAddress : (codeInfoAddress & 0xFFFF)
  65. const codeInfoMaxFrameBytes = storageAccessProtocol.resolveDescriptorMaxFrameBytes(
  66. protocolIoOptions.maxFrameBytes,
  67. codeInfoMaxPacketLength
  68. )
  69. if (!codeInfoByteLength || codeInfoByteLength > 0xFFFF) {
  70. showCodeInfoError(label, 'CodeInfo 信息块长度无效', protocolIoOptions)
  71. return null
  72. }
  73. const codeInfoBytes = await protocolIo.readMemory(
  74. codeInfoMemoryType,
  75. codeInfoReadAddress,
  76. codeInfoByteLength,
  77. label,
  78. kind,
  79. {
  80. ...protocolIoOptions,
  81. maxFrameBytes: codeInfoMaxFrameBytes,
  82. useDeviceCaps: false
  83. }
  84. )
  85. if (!codeInfoBytes) return null
  86. return {
  87. codeInfoAddress,
  88. codeInfoAddressWidth,
  89. codeInfoByteLength,
  90. codeInfoBytes,
  91. codeInfoDescriptorBytes: descriptorBytes,
  92. codeInfoMaxPacketLength,
  93. codeInfoMemoryEndian,
  94. codeInfoMemoryEndianMark: Number(descriptor.codeInfoMemoryEndianMark || 0) & 0xFFFF,
  95. codeInfoMemoryType
  96. }
  97. }
  98. async function syncCodeInfo(options = {}) {
  99. const result = await readCodeInfoBlock(
  100. options.label || '同步CodeInfo',
  101. options.kind || 'storage-code-info-read',
  102. {
  103. maxPacketLength: options.maxPacketLength,
  104. showModal: options.showModal !== false
  105. }
  106. )
  107. if (!result) {
  108. return {
  109. ok: false
  110. }
  111. }
  112. const descriptorCaps = {
  113. addressWidth: result.codeInfoAddressWidth,
  114. codeInfoByteLength: result.codeInfoByteLength,
  115. maxPacketLength: result.codeInfoMaxPacketLength,
  116. memoryEndian: result.codeInfoMemoryEndian,
  117. memoryEndianMark: result.codeInfoMemoryEndianMark
  118. }
  119. let codeInfo
  120. let importedGroups
  121. try {
  122. codeInfo = parseCodeInfo(result.codeInfoBytes, descriptorCaps)
  123. importedGroups = createGroupsFromCodeInfo(codeInfo, options)
  124. .map(cloneImportedGroup)
  125. .map(normalizeGroup)
  126. } catch (error) {
  127. const errorText = error.message || 'CodeInfo 解析失败'
  128. showCodeInfoError(options.label || '同步CodeInfo', errorText, options)
  129. return {
  130. errorText,
  131. ok: false
  132. }
  133. }
  134. protocolIo.updateSyncedDeviceCaps(descriptorCaps)
  135. return {
  136. codeInfoAddress: result.codeInfoAddress,
  137. codeInfoAddressText: formatDwordHex(result.codeInfoAddress),
  138. codeInfoAddressWidth: result.codeInfoAddressWidth,
  139. codeInfoByteLength: result.codeInfoByteLength,
  140. codeInfoByteLengthText: formatDwordHex(result.codeInfoByteLength),
  141. codeInfoBytes: result.codeInfoBytes,
  142. codeInfo,
  143. codeInfoDescriptorBytes: result.codeInfoDescriptorBytes,
  144. codeInfoMaxPacketLength: result.codeInfoMaxPacketLength,
  145. codeInfoMemoryEndian: result.codeInfoMemoryEndian,
  146. codeInfoMemoryEndianMark: result.codeInfoMemoryEndianMark,
  147. codeInfoMemoryType: result.codeInfoMemoryType,
  148. groupCount: importedGroups.length,
  149. importedGroups,
  150. ok: true,
  151. structCount: codeInfo.structCount
  152. }
  153. }
  154. module.exports = {
  155. readCodeInfoBlock,
  156. syncCodeInfo
  157. }