feat(protocol): 更新SPI Link协议至v2版本并优化CAN通信
- 将SPI OTA帧格式升级为SPI Link v2,采用新的帧格式: | SOF0 0xA5 | SOF1 0x5A | VER 0x02 | FLAGS | SESSION 4B LE | TX_SEQ | ACK_SEQ | CREDIT | TYPE | LEN 2B LE | RSV 2B | PAYLOAD | CRC32 4B LE | - 新增V2_OVERHEAD=20字节开销,APP最大payload为236字节,BOOT为108字节 - 修改帧类型定义:ENTER_BOOT从0xB5合并至0xB0,新增CAN业务类型0xC0~C3 - 更新CAN协议文档,支持SPI Link v2-only模式,调整最大业务payload计算 - 扩展0xC1帧功能,支持双向通信和1Hz主动推送ID快照 - 添加0xC3完整ID快照帧类型,包含seq/rx_count等完整字段 - 更新协议文档中的错误码定义和反馈payload格式 refactor(main): 重构主程序入口并添加CAN反馈任务 - 在main.cpp中添加CAN反馈任务,更新启动流程注释 - 创建createCriticalTask辅助函数,统一关键任务创建逻辑 - 调整SPI初始化顺序,确保CAN反馈任务依赖正确 - 优化错误处理机制,关键任务失败时立即重启 - 将GD32版本探测移至ota_relay任务处理 - 更新版本号至0.3.48,调整编译时间和Git哈希 config: 更新SPI和BLE配置参数 - 添加SPI主机相关配置参数,包括CS GPIO、READY GPIO等引脚定义 - 配置SPI缓冲区大小:APP为256字节,BOOT为128字节 - 更新BLE滑动窗口参数,ACK窗口设为32,数据队列深度为72 - 调整SPI工作队列大小至5120字节,增加任务堆栈监控说明
This commit is contained in:
+31
-4
@@ -6,8 +6,9 @@
|
||||
*
|
||||
* 依赖:dbc.js(state/el/padHex/bytesToHex/cssEscape/findSignal)、common/utils.js(escapeHtml)。
|
||||
*/
|
||||
import { state, el, padHex, bytesToHex, cssEscape, findSignal } from './dbc.js';
|
||||
import { escapeHtml as sanitizeHtml } from '../common/utils.js';
|
||||
import { state, el, padHex, bytesToHex, cssEscape, findSignal } from './dbc.js?v=20260717t';
|
||||
import { escapeHtml as sanitizeHtml } from '../common/utils.js?v=20260717t';
|
||||
import { scheduleCanPersist } from './persist.js?v=20260717t';
|
||||
|
||||
// ==================== 信号值存取 ====================
|
||||
/** @description 确保报文有 signalValues bag,并为每个信号填充默认值。返回 bag。 */
|
||||
@@ -182,6 +183,7 @@ function handleSignalInputEvent(evt) {
|
||||
if (inlineGrid) renderInlineSignalGrid(message, inlineGrid);
|
||||
}
|
||||
if (key === state.selectedMessageKey) updateEncodedPreview();
|
||||
scheduleCanPersist();
|
||||
}
|
||||
|
||||
function bindSignalInputs(container, message) {
|
||||
@@ -240,10 +242,21 @@ function renderByteStrip(bytes) {
|
||||
// ==================== 信号编解码(raw ↔ physical) ====================
|
||||
/** @description 将报文 + 信号值编码为 Uint8Array。 */
|
||||
export function encodeMessageData(message, signalValues) {
|
||||
var bytes = new Uint8Array(message.dlc);
|
||||
var dlc = message && message.dlc != null ? Number(message.dlc) : 0;
|
||||
if (!Number.isFinite(dlc) || dlc < 0) dlc = 0;
|
||||
if (dlc > 64) dlc = 64;
|
||||
/* DLC=0:无数据区(如 CANFD_BOOT),不写信号,直接空帧 */
|
||||
if (dlc === 0) {
|
||||
return new Uint8Array(0);
|
||||
}
|
||||
var bytes = new Uint8Array(dlc);
|
||||
var activeSignals = getActiveSignals(message);
|
||||
for (var i = 0; i < activeSignals.length; i++) {
|
||||
var signal = activeSignals[i];
|
||||
/* 信号完全落在 DLC 外则跳过,避免把空帧/定义异常拖成批量失败 */
|
||||
if (!signalFitsInDlc(signal, dlc)) {
|
||||
continue;
|
||||
}
|
||||
var parsed = parseSignalInput(signal, signalValues[signal.name]);
|
||||
if (signal.valueType === 'float' || signal.valueType === 'double') {
|
||||
writeFloatSignal(bytes, signal, parsed.numeric);
|
||||
@@ -254,6 +267,19 @@ export function encodeMessageData(message, signalValues) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/** @description 粗判信号位域是否至少有一部分落在 dlc 字节内(越界整段则跳过)。 */
|
||||
function signalFitsInDlc(signal, dlc) {
|
||||
if (!signal || dlc <= 0) return false;
|
||||
var maxBit = dlc * 8 - 1;
|
||||
if (signal.byteOrder === 'little') {
|
||||
var end = signal.startBit + signal.length - 1;
|
||||
return signal.startBit >= 0 && signal.startBit <= maxBit && end <= maxBit;
|
||||
}
|
||||
/* Motorola:用起始位所在字节粗判;更严的检查仍在 setBitByIndex */
|
||||
var startByte = Math.floor(signal.startBit / 8);
|
||||
return startByte >= 0 && startByte < dlc && signal.length > 0;
|
||||
}
|
||||
|
||||
function parseSignalInput(signal, inputValue) {
|
||||
var value = inputValue;
|
||||
if (value === '' || value == null) value = getDefaultSignalValue(signal);
|
||||
@@ -377,7 +403,8 @@ function setBitByIndex(bytes, bitIndex, bitValue) {
|
||||
var byteIndex = Math.floor(bitIndex / 8);
|
||||
var bitInByte = bitIndex % 8;
|
||||
if (byteIndex < 0 || byteIndex >= bytes.length) {
|
||||
throw new Error('信号写入越界,bit=' + bitIndex);
|
||||
throw new Error('信号写入越界,bit=' + bitIndex +
|
||||
'(缓冲区 ' + bytes.length + ' 字节 / DLC=' + bytes.length + ')');
|
||||
}
|
||||
if (bitValue) bytes[byteIndex] |= (1 << bitInByte);
|
||||
else bytes[byteIndex] &= ~(1 << bitInByte);
|
||||
|
||||
Reference in New Issue
Block a user