code-info-sync.js 5.2 KB

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