feat(ota): 优化握手请求处理及OTA会话状态管理
- 新增 OTA 会话激活状态标志 s_otaSessionActive 及其访问接口 - 在设置传输发送器时激活 OTA 会话状态 - OTAHandler 初始化时显式重置状态机,防止旧状态残留 - 严格区分握手请求 payload,避免 SPI OTA 握手误判状态 - 允许更多 OTA 状态接收握手请求,提升协议容错性 - 非空闲状态拒绝新握手请求并发送等待响应
This commit is contained in:
@@ -48,6 +48,7 @@ volatile u16 SpiOta::s_txLen = 0U;
|
|||||||
volatile bool SpiOta::s_txPending = false;
|
volatile bool SpiOta::s_txPending = false;
|
||||||
volatile bool SpiOta::s_isrResponded = false;
|
volatile bool SpiOta::s_isrResponded = false;
|
||||||
volatile bool SpiOta::s_isrLogPending = false;
|
volatile bool SpiOta::s_isrLogPending = false;
|
||||||
|
volatile bool SpiOta::s_otaSessionActive = false;
|
||||||
u8 SpiOta::s_isrLogBuf[kIsrLogBufSize] = {};
|
u8 SpiOta::s_isrLogBuf[kIsrLogBufSize] = {};
|
||||||
u16 SpiOta::s_isrLogLen = 0U;
|
u16 SpiOta::s_isrLogLen = 0U;
|
||||||
|
|
||||||
@@ -230,6 +231,7 @@ void SpiOta::isrProcessFrame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (s_otaHandler != nullptr) {
|
if (s_otaHandler != nullptr) {
|
||||||
|
s_otaSessionActive = true;
|
||||||
s_otaHandler->setTransportSender(sender);
|
s_otaHandler->setTransportSender(sender);
|
||||||
ota_link_msg_type_t msg_type = mapMsgType(frame_type);
|
ota_link_msg_type_t msg_type = mapMsgType(frame_type);
|
||||||
isrLogFrameEx("[OTA-MSG]", (const u8*)&frame_type, 1);
|
isrLogFrameEx("[OTA-MSG]", (const u8*)&frame_type, 1);
|
||||||
@@ -568,6 +570,8 @@ void SpiOta::feedRxBytes(const u8 *data, u16 len) {
|
|||||||
|
|
||||||
bool SpiOta::hasTxFrame() { return s_txPending; }
|
bool SpiOta::hasTxFrame() { return s_txPending; }
|
||||||
|
|
||||||
|
bool SpiOta::hasActiveSession() { return s_otaSessionActive; }
|
||||||
|
|
||||||
u16 SpiOta::copyTxFrame(u8 *out, u16 max_len) {
|
u16 SpiOta::copyTxFrame(u8 *out, u16 max_len) {
|
||||||
if (!out || max_len == 0U) { return 0U; }
|
if (!out || max_len == 0U) { return 0U; }
|
||||||
uint32_t primask = enterCritical();
|
uint32_t primask = enterCritical();
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public:
|
|||||||
static void onCsExtiInterrupt();
|
static void onCsExtiInterrupt();
|
||||||
static void feedRxBytes(const u8 *data, u16 len);
|
static void feedRxBytes(const u8 *data, u16 len);
|
||||||
static bool hasTxFrame();
|
static bool hasTxFrame();
|
||||||
|
static bool hasActiveSession();
|
||||||
static u16 copyTxFrame(u8 *out, u16 max_len);
|
static u16 copyTxFrame(u8 *out, u16 max_len);
|
||||||
|
|
||||||
static void isrProcessFrame();
|
static void isrProcessFrame();
|
||||||
@@ -59,6 +60,7 @@ public:
|
|||||||
static volatile bool s_txPending;
|
static volatile bool s_txPending;
|
||||||
static volatile bool s_isrResponded;
|
static volatile bool s_isrResponded;
|
||||||
static volatile bool s_isrLogPending;
|
static volatile bool s_isrLogPending;
|
||||||
|
static volatile bool s_otaSessionActive;
|
||||||
static u8 s_isrLogBuf[kIsrLogBufSize];
|
static u8 s_isrLogBuf[kIsrLogBufSize];
|
||||||
static u16 s_isrLogLen;
|
static u16 s_isrLogLen;
|
||||||
|
|
||||||
|
|||||||
@@ -213,6 +213,8 @@ static inline void send_structured_ack(uint32_t seq_or_flag) {
|
|||||||
void OTAHandler::init() {
|
void OTAHandler::init() {
|
||||||
/** 默认回包出口先绑定到 CAN。 */
|
/** 默认回包出口先绑定到 CAN。 */
|
||||||
transport_send = ota_can_sender;
|
transport_send = ota_can_sender;
|
||||||
|
/** 显式重置状态机,防止 APP 软跳转后残留旧状态。 */
|
||||||
|
resetToIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -478,17 +480,23 @@ void OTAHandler::handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len) {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* REQ: 握手/开始请求。
|
* REQ: 握手/开始请求。
|
||||||
* 空闲态回复 ACK(进入握手流程),非空闲态回复 WAIT。
|
*
|
||||||
|
* 只有 2 字节 payload (0x00 0xAC) 才是真正的握手请求。
|
||||||
|
* 16 字节 payload 是协议流程中的 nonce / confirm 数据,
|
||||||
|
* 需交由后续分支正常处理。
|
||||||
|
*
|
||||||
|
* 这解决了 CAN 总线帧在 SPI OTA 等待窗口内抢先改变
|
||||||
|
* ota_state 导致 SPI HANDSHAKE_REQ 收到 WAIT 的问题。
|
||||||
*/
|
*/
|
||||||
else if (type == OTA_LINK_MSG_REQ) {
|
else if (type == OTA_LINK_MSG_REQ && len == 2U && data[0] == 0x00U && data[1] == 0xACU) {
|
||||||
ota_time = 0;
|
ota_time = 0;
|
||||||
if (ota_state == OTA_STATE_IDLE) {
|
if (ota_state <= OTA_STATE_CHECKING_FIRMWARE) {
|
||||||
/* 空闲态收到 REQ,回复 ACK + echo 0x00 0xAC 表示 BOOT 就绪 */
|
/* 可重启态:IDLE / WAITING_RANDOM / WAITING_CONFIRM / CHECKING_FIRMWARE */
|
||||||
u8 ack_echo[2] = {0x00, 0xAC};
|
u8 ack_echo[2] = {0x00, 0xAC};
|
||||||
send_ack_frame(2, ack_echo);
|
send_ack_frame(2, ack_echo);
|
||||||
ota_state = OTA_STATE_WAITING_RANDOM;
|
ota_state = OTA_STATE_WAITING_RANDOM;
|
||||||
} else {
|
} else {
|
||||||
/* 非空闲态收到 REQ,回复 WAIT */
|
/* 已接收固件数据,拒绝新 REQ */
|
||||||
u8 wait_hint[1] = {0x01};
|
u8 wait_hint[1] = {0x01};
|
||||||
send_wait_frame(1, wait_hint);
|
send_wait_frame(1, wait_hint);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user