ESP32 Feather V2로 재활자전거 프로젝트를 진행하면서 핀을 배치할 때 GPIO 12에 외부 회로를 연결한 적이 있다. 코드도 문제없고 회로도 맞는 것 같은데 부팅이 안 됐다. 시리얼 모니터에는 flash read err, 1000 같은 에러 메시지가 반복해서 찍히며 리셋 루프에 빠졌다.

원인은 스트래핑 핀이었다.

스트래핑 핀이란

ESP32는 부팅할 때 특정 GPIO의 상태를 읽어서 동작 모드를 결정한다. 이 핀들을 스트래핑 핀(Strapping Pin) 이라고 부른다.

ESP32에서 주의해야 할 스트래핑 핀은 다음과 같다.

GPIO기능부팅 시 요구 상태
GPIO 0부트 모드 선택HIGH → 정상 실행, LOW → 다운로드 모드
GPIO 2다운로드 모드 조건다운로드 모드 진입 시 LOW여야 함
GPIO 12플래시 전압 선택LOW → 3.3V (정상), HIGH → 1.8V (부팅 실패)
GPIO 15부팅 로그 출력HIGH → 출력, LOW → 억제

이 중 GPIO 12가 가장 흔히 문제를 일으킨다.

GPIO 12가 특히 위험한 이유

GPIO 12(MTDI)는 부팅 시 내부 레귤레이터의 출력 전압을 결정하는 핀이다. 이 레귤레이터는 플래시 메모리와 PSRAM에 전원을 공급한다.

1
2
GPIO 12 = LOW (기본) → 플래시 전압 3.3V → 정상 부팅
GPIO 12 = HIGH       → 플래시 전압 1.8V → 플래시 읽기 실패 → 부팅 안 됨

GPIO 12에는 내부 풀다운이 내장되어 있다. 아무것도 연결하지 않으면 LOW로 유지되어 문제가 없다.

문제는 외부 회로를 연결했을 때다. 외부 회로가 부팅 순간에 GPIO 12를 HIGH로 당기면 ESP32가 플래시를 1.8V로 읽으려 하고, 실제 플래시는 3.3V 전용이라 데이터를 읽지 못한다. 그 결과 ROM 부트로더가 flash read err, 1000 에러를 출력하고 리셋을 반복한다.

더 까다로운 점은 증상이 일관적이지 않을 수 있다는 것이다. 커패시터 충전 타이밍에 따라 부팅 성공/실패가 들쭉날쭉하면 원인을 찾기가 더 어렵다.

해결 방법

방법 1: GPIO 12를 아예 피하기 (가장 확실)

핀이 충분하다면 처음부터 GPIO 12를 배치에서 제외하는 것이 가장 안전하다. 스트래핑 핀은 ESP32 데이터시트에 명시돼 있으니 핀 배치를 잡기 전에 미리 확인해두는 것이 좋다.

방법 2: 출력(OUTPUT)으로만 사용하기

스트래핑 핀 값은 부팅 직후, 코드가 실행되기 전에 읽힌다. 이 시점에 GPIO 12는 아직 코드의 제어를 받지 않으므로, 핵심은 외부 회로가 부팅 순간에 GPIO 12를 HIGH로 당기느냐다.

GPIO 12를 출력으로 사용한다면, 연결된 부품(모터 드라이버 EN 핀, 트랜지스터 베이스 등)이 부팅 시점에 LOW나 플로팅 상태인 경우가 많아 문제가 생기지 않는다. 반면 입력으로 사용할 경우 상대 회로가 부팅 순간 HIGH를 출력하면 위험하다.

연결된 부품이 부팅 시 HIGH를 출력할 가능성이 있다면 아래 방법 3을 함께 적용한다.

방법 3: 풀다운 저항 추가 (입력으로 써야 한다면)

GPIO 12에 10kΩ 풀다운을 추가해 부팅 시 LOW를 보장한다.

1
2
GPIO 12 ──┬── 외부 회로
           └── 10kΩ ── GND

정리

항목내용
증상외부 회로 연결 후 부팅 불가, 시리얼에 flash read err 에러 반복 출력
원인GPIO 12 스트래핑 핀 — 부팅 시 HIGH면 플래시 전압이 1.8V로 설정됨
해결GPIO 12 미사용 / 출력 전용으로 사용 / 풀다운 저항 추가

ESP32 핀 배치를 잡을 때는 스트래핑 핀 목록을 먼저 확인해두는 게 좋다. 특히 GPIO 12는 내부 풀다운이 있어서 단독으로는 문제없지만, 외부 회로가 붙는 순간 부팅 타이밍과 맞물려 아무 이유 없이 안 켜지는 것처럼 보일 수 있다.