feat(transport): 添加SPI Ready握手引脚支持并优化GPIO驱动依赖
添加ESP32-C3 GPIO驱动组件以支持SPI Ready握手机制,新增 SPI_READY_GPIO(10)引脚配置用于监测GD32 PB6就绪状态,避免SPI 通信时从机未准备好的丢帧问题。
This commit is contained in:
@@ -118,10 +118,12 @@ char* DebugLog::ringDrainJson(int *out_len)
|
||||
if (!out_len) return NULL;
|
||||
*out_len = 0;
|
||||
int count = ringCount();
|
||||
// ★ 限制单次导出条数,避免 count=64 时 malloc(32KB) 在堆紧张时失败
|
||||
// 前端每秒轮询,16 条/次足够保持实时性;超出的旧条目下一轮再拉
|
||||
static constexpr int kMaxDrain = 16;
|
||||
if (count > kMaxDrain) count = kMaxDrain;
|
||||
int capacity = count * (LOG_RING_SIZE * 2) + 16;
|
||||
if (capacity < 16) capacity = 16;
|
||||
// 当 count 较大(如 64)时 capacity 可能达 32KB+,单次 malloc 有风险。
|
||||
// 当前为简化实现保留单次 malloc;若后续日志量增大,可改为按 8KB 分块 realloc。
|
||||
char *buf = (char*)malloc(capacity);
|
||||
if (!buf) return NULL;
|
||||
|
||||
@@ -390,14 +392,27 @@ void DebugLog::log(debug_log_level_t level, const char *tag, const char *fmt, ..
|
||||
}
|
||||
snprintf(prefix, sizeof(prefix), "[%s][%s]", level_str, tag);
|
||||
|
||||
// 控制单条日志栈缓冲大小,避免调用任务(如 can_fb)因日志格式化爆栈。
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char msg[512];
|
||||
char msg[256];
|
||||
vsnprintf(msg, sizeof(msg), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
char log_buf[600];
|
||||
char log_buf[320];
|
||||
int total = snprintf(log_buf, sizeof(log_buf), "%s %s\n", prefix, msg);
|
||||
|
||||
// ★ snprintf 截断时返回"本应写入的长度"(可能 > sizeof(log_buf)),
|
||||
// 直接传给 send() 会越界读取栈外内存 → 破坏相邻任务 TCB → "Stack protection fault"
|
||||
// (崩溃栈中出现 HTTP User-Agent / "/ota/relay" 等字符串即此症状)。
|
||||
// 截断到实际缓冲区大小,避免越界读。
|
||||
if (total < 0) {
|
||||
return;
|
||||
}
|
||||
if ((size_t)total >= sizeof(log_buf)) {
|
||||
total = (int)sizeof(log_buf) - 1;
|
||||
log_buf[total] = '\0';
|
||||
}
|
||||
|
||||
send((const uint8_t *)log_buf, total);
|
||||
}
|
||||
|
||||
@@ -224,19 +224,6 @@ void HealthMonitor::taskEntry(void *pvParameters)
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 健康事件日志
|
||||
// ============================================================
|
||||
/**
|
||||
* @brief 记录一条健康事件日志。
|
||||
* @param event 事件名称。
|
||||
* @param value 事件值。
|
||||
*/
|
||||
void HealthMonitor::logEvent(const char *event, int value)
|
||||
{
|
||||
DEBUG_INFO("HEALTH", "[健康事件] %s: %d", event, value);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// OTA 健康检查
|
||||
// ============================================================
|
||||
@@ -353,30 +340,30 @@ void HealthMonitor::setWifiConnected(bool connected)
|
||||
*/
|
||||
health_status_t HealthMonitor::updateFromWifiRssi(int8_t rssi)
|
||||
{
|
||||
health_state_t cur = getState();
|
||||
health_state_t next = SYS_NORMAL;
|
||||
if (rssi < WIFI_RSSI_CRITICAL) {
|
||||
setState(SYS_CRITICAL);
|
||||
DEBUG_WARN("HEALTH", "WiFi RSSI 危险: %d dBm < %d dBm", rssi, WIFI_RSSI_CRITICAL);
|
||||
logEvent("WIFI危险", rssi);
|
||||
return HEALTH_MON_CRITICAL;
|
||||
next = SYS_CRITICAL;
|
||||
} else if (rssi < WIFI_RSSI_NORMAL) {
|
||||
health_state_t cur = getState();
|
||||
if (cur < SYS_WARNING) {
|
||||
setState(SYS_WARNING);
|
||||
DEBUG_WARN("HEALTH", "WiFi RSSI 警告: %d dBm < %d dBm", rssi, WIFI_RSSI_NORMAL);
|
||||
logEvent("WIFI警告", rssi);
|
||||
}
|
||||
return HEALTH_MON_WARNING;
|
||||
next = SYS_WARNING;
|
||||
}
|
||||
|
||||
// RSSI 已恢复正常(>= WIFI_RSSI_NORMAL):从 WARNING 或 CRITICAL 任一状态降级到 NORMAL。
|
||||
// 历史缺陷:原仅当 cur == SYS_WARNING 时降级,导致 CRITICAL 状态下 RSSI 恢复正常无法降级。
|
||||
// 注意:SAFE_SHUTDOWN 不应被 RSSI 恢复降级,仅处理 WARNING/CRITICAL。
|
||||
health_state_t cur = getState();
|
||||
if ((cur == SYS_WARNING || cur == SYS_CRITICAL) && rssi >= WIFI_RSSI_NORMAL) {
|
||||
setState(SYS_NORMAL);
|
||||
DEBUG_INFO("HEALTH", "WiFi RSSI 恢复: %d dBm >= %d dBm (从 %d 降级)", rssi, WIFI_RSSI_NORMAL, (int)cur);
|
||||
logEvent("WIFI恢复", rssi);
|
||||
// 仅在状态发生转换时打印一次,避免同一阈值下反复刷屏。
|
||||
if (next != cur) {
|
||||
if (next == SYS_CRITICAL) {
|
||||
setState(SYS_CRITICAL);
|
||||
DEBUG_WARN("HEALTH", "WiFi RSSI 危险: %d dBm < %d dBm", rssi, WIFI_RSSI_CRITICAL);
|
||||
} else if (next == SYS_WARNING) {
|
||||
setState(SYS_WARNING);
|
||||
DEBUG_WARN("HEALTH", "WiFi RSSI 警告: %d dBm < %d dBm", rssi, WIFI_RSSI_NORMAL);
|
||||
} else { // next == SYS_NORMAL,从 WARNING/CRITICAL 恢复
|
||||
setState(SYS_NORMAL);
|
||||
DEBUG_INFO("HEALTH", "WiFi RSSI 恢复: %d dBm >= %d dBm (从 %d 降级)", rssi, WIFI_RSSI_NORMAL, (int)cur);
|
||||
}
|
||||
}
|
||||
|
||||
if (next == SYS_CRITICAL) return HEALTH_MON_CRITICAL;
|
||||
if (next == SYS_WARNING) return HEALTH_MON_WARNING;
|
||||
|
||||
return HEALTH_MON_OK;
|
||||
}
|
||||
|
||||
@@ -65,8 +65,6 @@ public:
|
||||
/** @brief OTA 中继转发阶段执行健康检查(跳过 WiFi 检查)。 */
|
||||
health_status_t checkBeforeOtaRelay();
|
||||
|
||||
/** @brief 记录一条健康事件日志。 */
|
||||
void logEvent(const char *event, int value);
|
||||
|
||||
/** @brief 获取当前系统健康状态(线程安全)。 */
|
||||
health_state_t getCurrent();
|
||||
|
||||
Reference in New Issue
Block a user