ESP32 펌웨어 (PlatformIO: Arduino 우선, 필요 시 ESP-IDF)
코딩 표준, 아키텍처, 단위 테스트 및 일반 디버깅을 위해 embedded-c-cpp도 함께 로드하세요. 이 스킬은 ESP32 특화 부분을 담당합니다.
1단계: 프로젝트 식별
| 찾을 항목 | 위치 | 중요성 |
|---|---|---|
| 정확한 칩 및 모듈 (ESP32-WROOM-32E, ESP32-S3-WROOM-1-N16R8, ESP32-C3-MINI-1...) | platformio.ini board =, 사용자, 보드 실크스크린 | 코어, 핀, PSRAM, USB, ADC가 변형 간에 크게 다름 |
| 프레임워크 | framework = arduino, espidf, 또는 arduino, espidf | API 및 설정 모델 |
| Arduino 코어 버전 (2.x 또는 3.x) | 빌드 로그 라인 framework-arduinoespressif32 @ x.y.z, platform = 라인, 또는 ESP_ARDUINO_VERSION_MAJOR | 3.x에서 여러 API가 변경됨(LEDC, 타이머) — 잘못된 버전용 코드는 컴파일되지 않음 |
| 플래시 / PSRAM 크기 | 모듈 이름(N16R8 = 16MB 플래시, 8MB 옥탈 PSRAM), board_upload.flash_size | 파티션, 메모리 배치 |
| 보드 배선 | 사용자/회로도 | 스트래핑 핀 및 플래시/PSRAM/USB/LED가 사용하는 핀 회피 |
변형을 알 수 없고 작업이 핀, 주변장치, 전원 또는 메모리와 관련된 경우 코드를 작성하기 전에 먼저 확인하세요. S3에서 괜찮은 핀이 클래식 ESP32에서 부팅을 막을 수 있습니다.
Arduino인가 ESP-IDF인가?
| Arduino 기본값 유지 | ESP-IDF(PlatformIO: framework = espidf) 또는 Arduino + IDF(framework = arduino, espidf)로 이동 |
|---|---|
| 프로토타입 및 대부분의 제품 | sdkconfig 옵션 변경 필요 (롤백 OTA, 시큐어 부트, 플래시 암호화, PM 자동 라이트슬립, 코어 덤프-투-플래시, FreeRTOS 설정) — Arduino의 사전 컴파일된 코어는 노출하지 않음 |
| 많은 라이브러리 사용 가능 | 최신 IDF 기능, 메모리/성능의 세밀한 제어 |
| 빠른 반복 | 프로덕션 강화 |
ESP32의 Arduino는 이미 FreeRTOS + ESP-IDF 위에서 실행되므로 IDF API(esp_*, xTaskCreatePinnedToCore, nvs_*, esp_sleep_*, heap_caps_*)를 Arduino 코드에서 사용할 수 있습니다. "Arduino as IDF component"(arduino, espidf)는 Arduino 라이브러리를 유지하고 sdkconfig 제어를 추가합니다 — 일반적인 마이그레이션 경로입니다.
설정, platformio.ini 템플릿 및 2.x 대 3.x API 변경 사항은 references/platformio-setup.md를 참조하세요.
고전적인 ESP32 실패를 방지하는 규칙
- 핀: 플래시 핀(ESP32: GPIO6–11), PSRAM 핀(WROVER: 16/17; S3 옥탈 PSRAM 모듈: 33–37) 또는 USB 사용 시 USB 핀을 절대 사용하지 마세요. 스트래핑 핀(ESP32: 0, 2, 5, 12, 15)은 "주의해서만" 취급하세요 — GPIO12가 부트 시 풀업되면 3.3V 플래시 모듈이 부팅에 실패합니다. Wi-Fi가 켜져 있는 동안 ADC2는 작동하지 않습니다(클래식 ESP32): ADC1 핀을 사용하세요. 각 변형별 전체 표는
references/pins-and-variants.md를 참조하세요. loop()또는 태스크를 영원히 차단하지 마세요:delay()/vTaskDelay()없이 긴while루프는 태스크 감시 타이머를 트리거합니다.while (WiFi.status() != WL_CONNECTED)에는 타임아웃이 필요합니다.- ISR:
IRAM_ATTR로 표시하고, 아주 작게 유지하며,Serial.print,delay, Wi-Fi 호출을 사용하지 마세요. 작업을 태스크(큐/태스크 알림/플래그)로 위임하세요. 공유 변수는volatile+ 크리티컬 섹션(portENTER_CRITICAL_ISR스핀락 — ESP32는 듀얼 코어)을 사용하세요. - 태스크 스택은 바이트 단위입니다(ESP-IDF/Arduino에서 표준 FreeRTOS 워드와 다름).
uxTaskGetStackHighWaterMark(NULL)(바이트)로 측정하세요. Arduinoloop()의 기본값은 8KB입니다(SET_LOOP_TASK_STACK_SIZE(16 * 1024);로 변경). - 전원 공급: Wi-Fi TX는 약 300~500mA 피크를 소모합니다. "Browout detector was triggered"는 공급 장치(레귤레이터, 대용량 커패시터, 케이블)를 수리하라는 의미입니다 — 브라운아웃 검출기를 비활성화하지 마세요.
- 힙: 루프에서
String연결 및 빈번한new/malloc(수일간 단편화)을 피하고 미리 할당하세요. 시간 경과에 따라ESP.getFreeHeap()/heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT)를 확인하세요. - NVS/플래시 마모: 모든 루프 반복에서
Preferences/NVS에 쓰지 마세요. 변경 시에만, 속도 제한을 두고 쓰세요. - 되돌릴 수 없는 작업: eFuse 굽기, 시큐어 부트, 릴리스 모드의 플래시 암호화는 영구적입니다. 명시적인 사용자 확인 없이
espefuse.py burn_*를 실행하거나sdkconfig에서 이러한 기능을 활성화하거나 데이터가 있는 장치에서erase_flash를 절대 실행하지 마세요.
빌드, 업로드, 모니터 (PlatformIO)
pio run -e <env> # 빌드
pio run -e <env> -t upload # USB/시리얼로 플래싱
pio device monitor -e <env> # 시리얼 모니터 (monitor_speed / monitor_filters 사용)
pio run -e <env> -t upload -t monitor # 둘 다
pio run -e <env> -t uploadfs # data/ 폴더를 LittleFS/SPIFFS 이미지로 업로드
pio run -e <env> -t erase # 전체 플래시 지우기 (먼저 묻습니다: NVS/WiFi 인증 정보 삭제)
pio run -e <env> -t menuconfig # ESP-IDF / arduino+espidf 전용
pio test -e native # 호스트 단위 테스트 (embedded-c-cpp 참조)
업로드 실패 "Failed to connect / Wrong boot mode detected" → BOOT(GPIO0 / C3의 GPIO9) 누르고, EN/RST를 탭한 후 BOOT를 놓습니다. 케이블이 데이터를 전송하는지 확인하고; 포트를 잡고 있는 다른 시리얼 모니터를 닫습니다. 업로드 전에 보드가 연결되어 있고 포트를 확인하세요(pio device list).
충돌 또는 리부트 시
붙여넣을 수 있는 시리얼 출력이 핵적인 증거입니다. monitor_filters = esp32_exception_decoder와 build_type = debug를 활성화하여 백트레이스가 파일:라인으로 디코딩되도록 하세요. 그런 다음 references/panics-and-debug.md를 참조하세요: Guru Meditation 유형(LoadProhibited, StoreProhibited, IllegalInstruction, RISC-V의 Load/Store 액세스 폴트), 스택 카나리, 태스크/인터럽트 감시 타이머, rst: 코드, 브라운아웃, 부트 루프, JTAG 디버깅(S3/C3/C6의 debug_tool = esp-builtin)
참조 파일
| 파일 | 읽어야 할 상황 |
|---|---|
references/platformio-setup.md | platformio.ini 생성/수정, 플랫폼/코어 버전 선택, Arduino 2.x→3.x API 변경 사항, PSRAM, USB-CDC 시리얼, 파티션 및 파일시스템, PlatformIO에서 ESP-IDF 사용, sdkconfig |
references/pins-and-variants.md | 핀 선택 또는 검토, ESP32/S2/S3/C3/C6 비교, ADC, 터치, 딥슬립 웨이크 핀 |
references/rtos-memory-power.md | 태스크, 코어, ISR, 큐, 감시 타이머, 스택/힙/PSRAM, IRAM, 딥/라이트 슬립, 배터리 |
references/panics-and-debug.md | 모든 크래시, 리셋, 감시 타이머, 브라운아웃, 부트 루프, 업로드 실패, JTAG 디버그, 코어 덤프, 리셋 이유 |
references/connectivity-ota-security.md | Wi-Fi/BLE 안정성, NVS/Preferences, OTA 업데이트 및 롤백, 시큐어 부트 / 플래시 암호화 결정 |