/** * @file motor_version.cpp * @brief 多电机版本缓存实现 — CAN 版本应答帧(0x00FF)识别、缓存、0xC6 序列化。 * * 所有函数仅在主循环上下文调用(taskCanRxParse / pushStep),无 ISR 竞态。 * 与 motor_state.cpp 不同:版本是事件驱动(收到应答才缓存+推送),无周期任务、 * 无离线判定;pushStep 在 app_spi_cmd_motor_version.cpp(含 SPI 依赖)。 */ #include "device/motor_version.h" #include "device/spi/app_spi_command_defs.h" #include /* ── 全局版本表实例 ── */ static MotorVersionTable s_verTable = {}; namespace MotorVersion { MotorVersionTable &table() { return s_verTable; } void onCanFrame(uint8_t channel, uint32_t id, const uint8_t *data, uint8_t len) { (void)channel; /* 掩码匹配版本应答 ID: 0x000N00FF */ if ((id & kMotorVersionIdMask) != kMotorVersionIdMatch) { return; } const uint8_t node = static_cast((id >> 16) & 0x0FU); if (node < 1U || node > kMotorVersionMaxNodes) { return; } if (data == nullptr || len < 1U) { return; } MotorVersionSlot &slot = s_verTable.slots[node - 1U]; slot.node_id = node; slot.seq = ++s_verTable.global_seq; /* 拷贝原始 payload(不足补 0,超长截断) */ const uint8_t n = (len <= kMotorVersionDlc) ? len : kMotorVersionDlc; std::memcpy(slot.version, data, n); if (n < kMotorVersionDlc) { std::memset(&slot.version[n], 0, kMotorVersionDlc - n); } slot.dirty = 1U; /* 标记待推送 */ } bool hasPending() { for (uint8_t i = 0U; i < kMotorVersionMaxNodes; ++i) { if (s_verTable.slots[i].dirty != 0U) { return true; } } return false; } uint16_t buildPayload(uint8_t *buf, uint16_t maxLen) { if (buf == nullptr || maxLen < kMotorVersionHeaderLen) { return 0U; } /* Header (2B): count 稍后回填, rsvd=0 */ buf[0] = 0U; buf[1] = 0U; uint16_t offset = kMotorVersionHeaderLen; uint8_t count = 0U; for (uint8_t i = 0U; i < kMotorVersionMaxNodes; ++i) { MotorVersionSlot &slot = s_verTable.slots[i]; if (slot.dirty == 0U) { continue; } /* 检查剩余空间;装不下则保留 dirty 待下轮(不丢) */ if (offset + kMotorVersionEntrySize > maxLen) { break; } buf[offset + 0U] = slot.node_id; writeU32Le(&buf[offset + 1U], slot.seq); std::memcpy(&buf[offset + 5U], slot.version, kMotorVersionDlc); offset += kMotorVersionEntrySize; count++; slot.dirty = 0U; /* 已打包进本次推送 */ } if (count == 0U) { return 0U; } buf[0] = count; return offset; } } // namespace MotorVersion