fix: 修复:改进OTA错误处理和BLE OTA性能
- 重构app.js中的OTA错误处理,以准确报告获取失败而不假设重启,从而实现正确的状态轮询。 - 通过将握手状态封装在SpiLinkState类中来增强SPI主状态管理,提高清晰度并减少直接的状态操作。 引入otaSendAndPoll方法,以更好地处理SPI通信中的命令发送和响应轮询。 - 调整BLE OTA数据包确认逻辑,防止导致固件录变慢的虚假确认,确保仅在实际取得进展时才发送确认。 - 修改确认超时设置,以更好地适应闪存写入速度,减少不重传。
This commit is contained in:
@@ -30,34 +30,30 @@ static int sendCanFrameOverSpi(can_channel_t channel, uint32_t ext_id,
|
||||
|
||||
uint8_t resp_type = 0U;
|
||||
size_t resp_len = 0U;
|
||||
esp_err_t ret = SpiMaster::instance().otaTransfer(
|
||||
/* 两步法:otaTransfer 发命令(丢弃延迟一拍的过期响应)+ otaPollResponse 读真实响应。
|
||||
* CAN 帧非幂等,命令只发一次,不重发。 */
|
||||
esp_err_t ret = SpiMaster::instance().otaSendAndPoll(
|
||||
kSpiCanFrameType,
|
||||
tx_buf,
|
||||
tx_len,
|
||||
&resp_type,
|
||||
recv_buf,
|
||||
recv_max,
|
||||
&resp_len,
|
||||
timeout_ms);
|
||||
if (ret != ESP_OK || resp_type != SPI_OTA_RSP_ACK) {
|
||||
if (ret != ESP_OK) {
|
||||
DEBUG_WARN("CAN", "CAN_SEND SPI失败: ch=%u id=0x%08lX err=%s",
|
||||
(unsigned)channel, (unsigned long)ext_id, esp_err_to_name(ret));
|
||||
return -2; /* SPI 通信失败 */
|
||||
tx_buf, tx_len,
|
||||
&resp_type, recv_buf, recv_max, &resp_len, timeout_ms);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
DEBUG_WARN("CAN", "CAN_SEND SPI失败: ch=%u id=0x%08lX err=%s",
|
||||
(unsigned)channel, (unsigned long)ext_id, esp_err_to_name(ret));
|
||||
return -2; /* SPI 通信失败 */
|
||||
}
|
||||
if (resp_type == SPI_OTA_RSP_ACK) {
|
||||
if (recv_buf == nullptr || recv_max == 0U) {
|
||||
return static_cast<int>(resp_len);
|
||||
}
|
||||
/* resp_type != ACK: 读取 GD32 返回的错误码 */
|
||||
uint8_t gd32_err = (resp_len > 0 && recv_buf) ? recv_buf[0] : 0xFF;
|
||||
DEBUG_WARN("CAN", "CAN_SEND GD32拒绝: ch=%u id=0x%08lX resp=0x%02X err=0x%02X",
|
||||
(unsigned)channel, (unsigned long)ext_id, resp_type, gd32_err);
|
||||
return -3; /* GD32 返回 ERROR */
|
||||
const size_t copied_len = (resp_len < recv_max) ? resp_len : recv_max;
|
||||
return static_cast<int>(copied_len);
|
||||
}
|
||||
|
||||
if (recv_buf == nullptr || recv_max == 0U) {
|
||||
return static_cast<int>(resp_len);
|
||||
}
|
||||
|
||||
const size_t copied_len = (resp_len < recv_max) ? resp_len : recv_max;
|
||||
return static_cast<int>(copied_len);
|
||||
/* resp_type == ERROR: 读取 GD32 返回的错误码 */
|
||||
uint8_t gd32_err = (resp_len > 0 && recv_buf) ? recv_buf[0] : 0xFF;
|
||||
DEBUG_WARN("CAN", "CAN_SEND GD32拒绝: ch=%u id=0x%08lX resp=0x%02X err=0x%02X",
|
||||
(unsigned)channel, (unsigned long)ext_id, resp_type, gd32_err);
|
||||
return -3; /* GD32 返回 ERROR */
|
||||
}
|
||||
|
||||
constexpr uint8_t kSpiCanFeedbackType = 0xC1U;
|
||||
@@ -202,7 +198,7 @@ int canFdPullIdSnapshot(can_channel_t channel,
|
||||
uint8_t resp_type = 0U;
|
||||
size_t resp_len = 0U;
|
||||
|
||||
esp_err_t ret = SpiMaster::instance().otaTransfer(
|
||||
esp_err_t ret = SpiMaster::instance().otaSendAndPoll(
|
||||
kSpiIdSnapshotType,
|
||||
req, 2U,
|
||||
&resp_type, resp_buf, sizeof(resp_buf), &resp_len, timeout_ms);
|
||||
@@ -263,15 +259,18 @@ int canFdSetRxMode(can_rx_mode_t mode,
|
||||
uint8_t resp_type = 0U;
|
||||
size_t resp_len = 0U;
|
||||
|
||||
esp_err_t ret = SpiMaster::instance().otaTransfer(
|
||||
/* 两步法破解延迟一拍:发命令一次 + poll 真实响应。
|
||||
* 0xC2 幂等,但两步法避免无效重试。 */
|
||||
esp_err_t ret = SpiMaster::instance().otaSendAndPoll(
|
||||
kSpiCanSetModeType,
|
||||
&req, 1U,
|
||||
&resp_type, resp_buf, sizeof(resp_buf), &resp_len, timeout_ms);
|
||||
if (ret != ESP_OK || resp_type != SPI_OTA_RSP_ACK || resp_len < 1U) {
|
||||
return -1;
|
||||
|
||||
if (ret == ESP_OK && resp_type == SPI_OTA_RSP_ACK && resp_len >= 1U) {
|
||||
if (actual != nullptr) {
|
||||
*actual = static_cast<can_rx_mode_t>(resp_buf[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (actual != nullptr) {
|
||||
*actual = static_cast<can_rx_mode_t>(resp_buf[0]);
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user