feat(build): 优化构建配置并引入日志分级系统

- 将优化级别从balanced调整为size,减少Flash占用
- 添加hardfault.cpp文件以增强故障诊断能力
- 关闭RTTI和异常处理以移除libcppabi运行时(节省约2.5KB Flash)
- 添加链接器参数输出未引用段与总量报告用于Flash尺寸分析

refactor(logging): 统一日志输出并实现编译时日志分级

- 将printf调用替换为模块化的日志宏(ECAT_LOGI、CAN_LOGI等)
- 实现CONFIG_*_LOG_ENABLE编译开关控制各模块INFO级日志
- 错误和关键事件使用LOG_ERR恒定保留,其他日志可编译时裁剪
- 保持原有日志内容不变,但支持链接器自动回收未使用的格式字符串
This commit is contained in:
cbb
2026-07-27 01:49:18 +08:00
parent edebde4a02
commit 46ef19d882
9 changed files with 130 additions and 88 deletions
+26 -26
View File
@@ -195,7 +195,7 @@ static void keyedCrc32(const uint8_t *key, const uint8_t *data, uint8_t *output)
static bool canSend(uint32_t id, const uint8_t *data, uint8_t dlc, bool periodic = false) {
/* 诊断:kTransfer 期间只应发 0x101,若出现 0x100 则为幽灵帧 */
if (s_state == State::kTransfer && id == kOtaReqId) {
printf("[MOTOR-OTA] BUG! canSend(0x100) in kTransfer! dlc=%u\r\n", (unsigned)dlc);
LOG_ERR("[MOTOR-OTA] BUG! canSend(0x100) in kTransfer! dlc=%u\r\n", (unsigned)dlc);
}
const CanFd::CanTxResult r = CanFd::transmitFrame(s_channel, id, data, dlc, periodic);
return (r == CanFd::CanTxResult::kOk);
@@ -321,7 +321,7 @@ static void sendNonce() {
/* 统一重发当前步骤的帧(超时重发 + kHandshakeReq 首发) */
static void sendCurrentStep(uint32_t now_ms) {
printf("[MOTOR-OTA] TX %s try=%u t=%lu\r\n",
OTA_LOGI("[MOTOR-OTA] TX %s try=%u t=%lu\r\n",
stepName(s_state), (unsigned)s_retry_count, (unsigned long)now_ms);
switch (s_state) {
case State::kHandshakeReq: {
@@ -413,14 +413,14 @@ static void sendCurrentPacket() {
/* 末包 padding 日志在 TX 前打印(sendNextPacket 设 s_last_pad_valid)。
* 用最短格式 + 一次性打印(打印后置 0xFFFF 防重发重复打印)。 */
if (s_last_pad_valid != 0xFFFFU) {
printf("[MOTOR-OTA] PAD v=%u p=%u\r\n",
OTA_LOGI("[MOTOR-OTA] PAD v=%u p=%u\r\n",
(unsigned)s_last_pad_valid,
(unsigned)(kPacketPayload - s_last_pad_valid));
s_last_pad_valid = 0xFFFFU;
}
/* 逐包 TX 日志在 5ms 节奏下会拖主循环;仅末包/每 64 包打一行。 */
if (is_last || ((pkt_num & 0x3FU) == 0U)) {
printf("[MOTOR-OTA] TX pkt=%lu/%u%s t=%lu\r\n",
OTA_LOGI("[MOTOR-OTA] TX pkt=%lu/%u%s t=%lu\r\n",
(unsigned long)pkt_num, (unsigned)s_total_packets,
is_last ? " LAST" : "", (unsigned long)SysTickTimer::getMs());
}
@@ -445,7 +445,7 @@ static void sendNextPacket() {
static uint32_t s_last_tail_ms = 0;
const uint32_t now = SysTickTimer::getMs();
if (now - s_last_tail_ms >= 200U) {
printf("[MOTOR-OTA] 末包欠载,等尾字节 pkt=%u used=%u need=%u fed=%lu t=%lu\r\n",
OTA_LOGI("[MOTOR-OTA] tail-wait pkt=%u used=%u need=%u fed=%lu t=%lu\r\n",
(unsigned)s_packets_acked, (unsigned)used,
(unsigned)last_valid, (unsigned long)s_fw_fed,
(unsigned long)now);
@@ -466,7 +466,7 @@ static void sendNextPacket() {
static uint32_t s_last_empty_ms = 0;
const uint32_t now = SysTickTimer::getMs();
if (now - s_last_empty_ms >= 200U) {
printf("[MOTOR-OTA] 缓冲空,等ESP32喂 pkt=%u used=%u fed=%lu/%lu t=%lu\r\n",
OTA_LOGI("[MOTOR-OTA] buf-empty wait-feed pkt=%u used=%u fed=%lu/%lu t=%lu\r\n",
(unsigned)s_packets_acked, (unsigned)used,
(unsigned long)s_fw_fed, (unsigned long)s_fw_size,
(unsigned long)now);
@@ -533,7 +533,7 @@ static void processTransferAck(const uint8_t *data, uint8_t len) {
s_crc_resend_pending = true;
return;
}
printf("[MOTOR-OTA] CRC 重试耗尽 pkt=%u/%u dup=%lu crc=%lu\r\n",
LOG_ERR("[MOTOR-OTA] CRC retry exhausted pkt=%u/%u dup=%lu crc=%lu\r\n",
(unsigned)s_packets_acked, (unsigned)s_total_packets,
(unsigned long)s_dup_ack_count, (unsigned long)s_crc_err_count);
setError(0x23); /* CRC 重试耗尽 */
@@ -543,7 +543,7 @@ static void processTransferAck(const uint8_t *data, uint8_t len) {
/* INVALID_HANDSHAKE(0x05):电机 BOOT 已退回 IDLE。按用户要求不再做
* 「发 CANCEL + 从包 0 重握手」的自动重试(会白扔进度、坏总线下反复失败),
* 直接中止,由上位机决定是否整体重刷。 */
printf("[MOTOR-OTA] HANDSHAKE 错误(0x05),中止(不重握手) pkt=%u/%u\r\n",
LOG_ERR("[MOTOR-OTA] HANDSHAKE err(0x05) abort pkt=%u/%u\r\n",
(unsigned)s_packets_acked, (unsigned)s_total_packets);
setError(0x05);
return;
@@ -579,7 +579,7 @@ if (next_pkt == 0xFFFFFFFFU) {
s_packets_acked = s_total_packets;
s_last_acked_pkt = s_total_packets;
s_pkt_pending = false;
printf("[MOTOR-OTA] FINISHED pkt=%u/%u dup=%lu crc=%lu resend=%lu fast=%lu t=%lu\r\n",
LOG_ERR("[MOTOR-OTA] FINISHED pkt=%u/%u dup=%lu crc=%lu resend=%lu fast=%lu t=%lu\r\n",
(unsigned)s_packets_acked, (unsigned)s_total_packets,
(unsigned long)s_dup_ack_count, (unsigned long)s_crc_err_count,
(unsigned long)s_ack_resend_total, (unsigned long)s_fast_resend_total,
@@ -624,7 +624,7 @@ if (next_pkt == 0xFFFFFFFFU) {
* 与 0xD1 喂数抢总线,加重缓冲欠载(CANlog 可见周期性 ~500ms 空洞)。
* 进度由 ESP32 feedTask 按已喂字节估算;终态再 push。 */
if ((s_packets_acked & 0x1F) == 0) {
printf("[MOTOR-OTA] 进度 pkt=%u/%u dup=%lu crc=%lu resend=%lu fast=%lu t=%lu\r\n",
OTA_LOGI("[MOTOR-OTA] progress pkt=%u/%u dup=%lu crc=%lu resend=%lu fast=%lu t=%lu\r\n",
(unsigned)s_packets_acked, (unsigned)s_total_packets,
(unsigned long)s_dup_ack_count, (unsigned long)s_crc_err_count,
(unsigned long)s_ack_resend_total, (unsigned long)s_fast_resend_total,
@@ -662,7 +662,7 @@ void onTxTick() {
s_retry_count++;
s_fast_resend_total++;
const uint32_t err = CanFd::readChannelErrorReg(s_channel);
printf("[MOTOR-OTA] TX错快重发 pkt=%u retry=%u tec=%lu rec=%lu errn=%lu\r\n",
LOG_ERR("[MOTOR-OTA] TX-err fast-resend pkt=%u retry=%u tec=%lu rec=%lu errn=%lu\r\n",
(unsigned)s_packets_acked, (unsigned)s_retry_count,
(unsigned long)((err >> 16) & 0xFFU),
(unsigned long)((err >> 24) & 0xFFU),
@@ -678,7 +678,7 @@ void onTxTick() {
/* 事件时刻 CAN_ERR 快照:钉死丢帧时总线状态(TEC 涨=数据帧发丢,
* REC 高=接收方向损坏),摆脱 1Hz [CAN-BUS] 采样混叠。仅日志,不做发送门控。 */
const uint32_t err = CanFd::readChannelErrorReg(s_channel);
printf("[MOTOR-OTA] ACK 超时重发 pkt=%u retry=%u tec=%lu rec=%lu errn=%lu\r\n",
LOG_ERR("[MOTOR-OTA] ACK timeout resend pkt=%u retry=%u tec=%lu rec=%lu errn=%lu\r\n",
(unsigned)s_packets_acked, (unsigned)s_retry_count,
(unsigned long)((err >> 16) & 0xFFU),
(unsigned long)((err >> 24) & 0xFFU),
@@ -723,7 +723,7 @@ if (s_pkt_pending) return; /* 当前包待确认,不发新包
if (!is_last && !all_fed && used < water) {
static uint32_t s_last_water_ms = 0;
if (now - s_last_water_ms >= 200U) {
printf("[MOTOR-OTA] 等SPI水位 used=%u need=%u fed=%lu pkt=%u\r\n",
OTA_LOGI("[MOTOR-OTA] wait-SPI-level used=%u need=%u fed=%lu pkt=%u\r\n",
(unsigned)used, (unsigned)water,
(unsigned long)s_fw_fed, (unsigned)s_packets_acked);
s_last_water_ms = now;
@@ -749,12 +749,12 @@ void process() {
* 再开始握手就不会被干扰。 */
if (s_state == State::kPreCancel) {
if (s_boot_heartbeat_seen && stateTimedOut(kBootSettleMs)) {
printf("[MOTOR-OTA] 0x103 心跳确认 + %ums 残帧窗口已过,开始握手\r\n",
OTA_LOGI("[MOTOR-OTA] 0x103 ok, residue-win %ums passed, handshake\r\n",
(unsigned)kBootSettleMs);
enterState(State::kHandshakeReq);
pushStatus();
} else if (stateTimedOut(kHandshakeTimeoutMs)) {
printf("[MOTOR-OTA] 等待 0x103 超时,电机未进入 BOOT\r\n");
LOG_ERR("[MOTOR-OTA] wait 0x103 timeout, motor not in BOOT\r\n");
setError(0x02); /* 0x02 = 电机未进入 BOOT */
}
return;
@@ -785,7 +785,7 @@ void process() {
if (rnow - s_last_rxerr_ms >= 200U) { rx_do_log = true; s_last_rxerr_ms = rnow; }
}
if (rx_do_log) {
printf("[MOTOR-OTA] RX %s pkt=%u/%u len=%u b0=%02X b1=%02X t=%lu\r\n",
OTA_LOGI("[MOTOR-OTA] RX %s pkt=%u/%u len=%u b0=%02X b1=%02X t=%lu\r\n",
stepName(s_state), (unsigned)s_packets_acked, (unsigned)s_total_packets,
(unsigned)ack_len,
(ack_len > 0) ? ack_data[0] : 0xFFU, (ack_len > 1) ? ack_data[1] : 0xFFU,
@@ -800,7 +800,7 @@ void process() {
enterState(State::kHandshakeNonce);
canSend(kOtaReqId, s_nonce, 16);
s_last_send_ms = SysTickTimer::getMs();
printf("[MOTOR-OTA] TX HANDSHAKE_NONCE(0x100:16B) [ACK-driven] t=%lu\r\n",
OTA_LOGI("[MOTOR-OTA] TX HANDSHAKE_NONCE(0x100:16B) [ACK-driven] t=%lu\r\n",
(unsigned long)s_last_send_ms);
}
/* 不匹配的 ACK 靠掉 —— 忽略,等超时重发 REQ */
@@ -809,13 +809,13 @@ void process() {
case State::kHandshakeNonce:
if (ack_len < 36) {
/* 短帧(0x05/干扰) —— 忽略,等真正 48B 或超时重发 */
printf("[MOTOR-OTA] NONCE ACK 忽略短帧 len=%u b0=0x%02X\r\n",
LOG_ERR("[MOTOR-OTA] NONCE ACK ignore short frame len=%u b0=0x%02X\r\n",
(unsigned)ack_len, (ack_len > 0) ? ack_data[0] : 0xFFU);
break;
}
if (memcmp(ack_data + 12, s_nonce + 8, 8) != 0) {
/* nonce echo 不匹配 —— 电机收到了错误的帧当 nonce */
printf("[MOTOR-OTA] NONCE ACK echo mismatch, ignore\r\n");
LOG_ERR("[MOTOR-OTA] NONCE ACK echo mismatch, ignore\r\n");
break;
}
/* ✔ nonce 响应正确 —— 派生 K_session,立即发 confirm */
@@ -834,7 +834,7 @@ void process() {
aes128_encrypt_block(&s_aes_ctx, plain, confirm);
canSend(kOtaReqId, confirm, 16);
s_last_send_ms = SysTickTimer::getMs();
printf("[MOTOR-OTA] TX HANDSHAKE_CONFIRM(0x100:16B) [ACK-driven] t=%lu\r\n",
OTA_LOGI("[MOTOR-OTA] TX HANDSHAKE_CONFIRM(0x100:16B) [ACK-driven] t=%lu\r\n",
(unsigned long)s_last_send_ms);
}
break;
@@ -850,7 +850,7 @@ void process() {
size_le[3] = static_cast<uint8_t>((s_fw_size >> 24) & 0xFF);
canSend(kOtaDataId, size_le, 4);
s_last_send_ms = SysTickTimer::getMs();
printf("[MOTOR-OTA] TX ERASE(0x101:fw_size) [ACK-driven] t=%lu\r\n",
OTA_LOGI("[MOTOR-OTA] TX ERASE(0x101:fw_size) [ACK-driven] t=%lu\r\n",
(unsigned long)s_last_send_ms);
}
/* 非 [BA C0] —— 忽略(可能是 0x03/0x05 干扰帧) */
@@ -867,7 +867,7 @@ void process() {
* 过时的 0x100 帧 → catch-all → [05] 杀死 OTA。强制 abort 降低风险。 */
CanFd::abortPendingTx(s_channel);
s_last_send_ms = SysTickTimer::getMs();
printf("[MOTOR-OTA] ERASE ACK 收到,等 %ums 再发首包\r\n",
OTA_LOGI("[MOTOR-OTA] ERASE ACK ok, wait %ums then first pkt\r\n",
(unsigned)kEraseWaitMs);
}
/* 非 [BA C0 ...] —— 忽略,等超时重发 fw_size */
@@ -906,7 +906,7 @@ void process() {
} else if ((now_ms - s_last_send_ms) >= kStepTimeoutMs) {
/* 超时重发 */
if (s_retry_count >= kMaxResends) {
printf("[MOTOR-OTA] %s 未收到应答(已发送 %u 次无响应),中止刷写\r\n",
LOG_ERR("[MOTOR-OTA] %s no-ACK after %u tries, abort\r\n",
stepName(s_state), (unsigned)(kMaxResends + 1U));
setError(static_cast<uint8_t>(0x30U + static_cast<uint8_t>(s_state)));
pushStatus();
@@ -989,7 +989,7 @@ s_channel = can_channel;
/* 不在 SPI 中断里同步发握手帧(电机跳 BOOT 期间 CAN 可能短暂断开)。
* 先进 kPreCancel 等待电机 0x103 心跳确认已进 BOOT,再由 process() 异步推进到握手。 */
printf("[MOTOR-OTA] START ch=%u fw=%lu total=%u\r\n",
LOG_ERR("[MOTOR-OTA] START ch=%u fw=%lu total=%u\r\n",
(unsigned)can_channel, (unsigned long)fw_size, (unsigned)s_total_packets);
s_boot_heartbeat_seen = false;
enterState(State::kPreCancel);
@@ -1040,7 +1040,7 @@ bool feedData(const uint8_t *data, uint16_t len) {
static uint32_t s_last_gap_ms = 0;
const uint32_t now = SysTickTimer::getMs();
if (now - s_last_gap_ms >= 200U) {
printf("[MOTOR-OTA] feed 缺口 off=%lu fed=%lu len=%u\r\n",
LOG_ERR("[MOTOR-OTA] feed gap off=%lu fed=%lu len=%u\r\n",
(unsigned long)offset, (unsigned long)s_fw_fed,
(unsigned)chunk_len);
s_last_gap_ms = now;
@@ -1061,7 +1061,7 @@ bool feedData(const uint8_t *data, uint16_t len) {
void cancel() {
if (s_state == State::kIdle) return;
printf("[MOTOR-OTA] CANCEL received in state %s\r\n", stepName(s_state));
LOG_ERR("[MOTOR-OTA] CANCEL received in state %s\r\n", stepName(s_state));
/* ★ kFinished/kError 时电机已跳转 APP 或已中止,绝不能再发 CAN 取消帧!
* kOtaCancelId=0x00000000 与电机 APP 的 CANFD_BOOT_ID(base_id=0x0000) 冲突,
* 电机 APP 收到会当作 BOOT 命令 → enter_silent_mode 10s,APP 看似卡死。