From 8a33481a2cb90665c4c5ef3b57bba8cbe96c21be Mon Sep 17 00:00:00 2001 From: byun Date: Mon, 19 Jan 2026 22:00:11 +0000 Subject: [PATCH] =?UTF-8?q?sd=EC=B9=B4=EB=93=9C=20=ED=94=8C=EB=9F=AC?= =?UTF-8?q?=EC=89=AC=20=ED=9A=9F=EC=88=98=20=EA=B0=90=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ESP32_CAN_Logger-a.ino | 86 +++++++++++------------------------------- 1 file changed, 21 insertions(+), 65 deletions(-) diff --git a/ESP32_CAN_Logger-a.ino b/ESP32_CAN_Logger-a.ino index 97b6921..906ca4a 100644 --- a/ESP32_CAN_Logger-a.ino +++ b/ESP32_CAN_Logger-a.ino @@ -1421,8 +1421,9 @@ void canRxTask(void *parameter) { } } - // 메시지 읽기 - while (mcp2515.readMessage(&frame) == MCP2515::ERROR_OK) { + // 메시지 배치 읽기 (한 번에 최대 20개 처리) + int batchCount = 0; + while (batchCount < 20 && mcp2515.readMessage(&frame) == MCP2515::ERROR_OK) { struct timeval tv; // 🎯 Auto Trigger 체크 checkAutoTriggers(frame); @@ -1433,9 +1434,15 @@ void canRxTask(void *parameter) { msg.dlc = frame.can_dlc; memcpy(msg.data, frame.data, 8); - if (xQueueSend(canQueue, &msg, pdMS_TO_TICKS(10)) == pdTRUE) { + if (xQueueSend(canQueue, &msg, 0) == pdTRUE) { // ⭐ 타임아웃 10ms → 0 (블로킹 제거) totalMsgCount++; } + batchCount++; + } + + // 배치 처리 후 짧은 yield (다른 Task에 CPU 양보) + if (batchCount == 0) { + vTaskDelay(pdMS_TO_TICKS(1)); } } } @@ -1501,36 +1508,14 @@ void sdWriteTask(void *parameter) { currentFileSize += lineLen; static int csvFlushCounter = 0; - if (++csvFlushCounter >= 50) { // ⭐ 20 → 50 (너무 자주 플러시하면 느림) + if (++csvFlushCounter >= 500) { // ⭐ 200 → 500 (최대 성능) logFile.flush(); csvFlushCounter = 0; } - // ⭐⭐⭐ 2000개마다 파일 재오픈 (500 → 2000 변경, SDIO 안정성) - if (++csvReopenCounter >= 2000) { - logFile.close(); - delay(50); // SD 카드 안정화 대기 - - // 파일 재오픈 (재시도 로직) - bool reopenSuccess = false; - for (int retry = 0; retry < 3; retry++) { - logFile = SD_MMC.open(currentFilename, FILE_APPEND); - if (logFile) { - Serial.printf("✓ CSV 파일 재오픈: %s (%lu bytes)\n", currentFilename, currentFileSize); - reopenSuccess = true; - break; - } else { - Serial.printf("⚠ CSV 파일 재오픈 실패, 재시도 %d/3\n", retry + 1); - delay(100); // 재시도 전 대기 - } - } - - if (!reopenSuccess) { - Serial.println("✗ CSV 파일 재오픈 완전 실패! 로깅 중지"); - loggingEnabled = false; - } - csvReopenCounter = 0; - } + // ⭐⭐⭐ 파일 재오픈 제거 (고부하 환경 최적화) + // if (++csvReopenCounter >= 2000) { ... } // 제거됨 + } } else { @@ -1555,8 +1540,8 @@ void sdWriteTask(void *parameter) { binMsgCounter++; binReopenCounter++; - // ⭐⭐⭐ 3단계: 100개 메시지마다 주기적 플러시 - if (binMsgCounter % 100 == 0) { + // ⭐⭐⭐ 3단계: 1000개 메시지마다 주기적 플러시 (500→1000, 최대 성능) + if (binMsgCounter % 1000 == 0) { if (logFile && bufferIndex > 0) { size_t written = logFile.write(fileBuffer, bufferIndex); logFile.flush(); @@ -1565,40 +1550,11 @@ void sdWriteTask(void *parameter) { } } - // ⭐⭐⭐ 4단계: 2000개마다 파일 재오픈 (500 → 2000 변경, SDIO 안정성) - if (binReopenCounter >= 2000) { - // 버퍼 먼저 플러시 - if (logFile && bufferIndex > 0) { - logFile.write(fileBuffer, bufferIndex); - logFile.flush(); - bufferIndex = 0; - } - - // 파일 닫기 - logFile.close(); - delay(50); // SD 카드 안정화 대기 - - // 파일 재오픈 (재시도 로직) - bool reopenSuccess = false; - for (int retry = 0; retry < 3; retry++) { - logFile = SD_MMC.open(currentFilename, FILE_APPEND); - if (logFile) { - Serial.printf("✓ BIN 파일 재오픈: %s (%lu bytes)\n", currentFilename, currentFileSize); - reopenSuccess = true; - break; - } else { - Serial.printf("⚠ BIN 파일 재오픈 실패, 재시도 %d/3\n", retry + 1); - delay(100); // 재시도 전 대기 - } - } - - if (!reopenSuccess) { - Serial.println("✗ BIN 파일 재오픈 완전 실패! 로깅 중지"); - loggingEnabled = false; - } - - binReopenCounter = 0; - } + // ⭐⭐⭐ 4단계: 파일 재오픈 제거 (고부하 환경 최적화) + // 재오픈 시 SD 카드 블록으로 인한 오버플로우 방지 + // 대신 주기적 flush로 데이터 안정성 확보 + // if (binReopenCounter >= 2000) { ... } // 제거됨 + } xSemaphoreGive(sdMutex); }