1
0

code-info-sync.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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 || 'little').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. memoryEndian: codeInfoMemoryEndian,
  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: formatHexNumber(result.codeInfoAddress, 8),
  138. codeInfoAddressWidth: result.codeInfoAddressWidth,
  139. codeInfoByteLength: result.codeInfoByteLength,
  140. codeInfoByteLengthText: formatHexNumber(result.codeInfoByteLength, 8),
  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. entryCount: codeInfo.entryCount,
  149. enumCount: codeInfo.enumCount,
  150. groupCount: importedGroups.length,
  151. importedGroups,
  152. ok: true,
  153. arrayCount: codeInfo.arrayCount,
  154. structCount: codeInfo.structCount,
  155. variableCount: codeInfo.variableCount
  156. }
  157. }
  158. module.exports = {
  159. readCodeInfoBlock,
  160. syncCodeInfo
  161. }