1. Тема дня

GPIO-ограничения ESP32/ESP32-C3 и правила выбора пинов: strapping pins, UART0, flash/PSRAM- пины, JTAG/SWD, input-only GPIO, ADC2 при Wi-Fi, оформление board_pins.h. Главная мысль: В embedded нельзя выбирать GPIO только по принципу “свободная ножка”. У каждой ножки есть история: загрузка, flash, отладка, аналоговые ограничения, подтяжки, sleep/wakeup и периферийные функции.

2. Зачем это нужно

В проектах важны:

  • UART2 для EC25: TX17/RX16 на ESP32-WROOM-32U;
  • UART0 для CLI/прошивки;
  • входы светофора;
  • GPIO для PWRKEY/RESET EC25;
  • GPIO для питания камеры/радара/Jetson;
  • 1-Wire DS18B20;
  • синхросигналы PPS/20 Гц;
  • HIL через Raspberry Pi;
  • перенос на STM32.

Ошибки выбора GPIO дают странные симптомы:

  • плата иногда не стартует;
  • прошивка не заливается;
  • ESP32 уходит в download mode;
  • UART лог молчит;
  • Wi-Fi ломает ADC;
  • JTAG/SWD не работает;
  • внешний вход влияет на режим загрузки.

3. Strapping pins

Strapping pins - пины, которые микроконтроллер считывает при reset/startup, чтобы выбрать параметры загрузки. Для классического ESP32:

text
GPIO0
GPIO2
GPIO5
GPIO12 / MTDI
GPIO15 / MTDO

Для ESP32-C3:

text
GPIO2
GPIO8
GPIO9

После старта они могут работать как обычные GPIO, но уровень на reset уже повлиял на загрузку.

4. GPIO0

text
GPIO0 = LOW при reset  -> serial bootloader / download mode
GPIO0 = HIGH при reset -> normal execution from flash

Практический вывод: GPIO0 нельзя бездумно вешать на внешний сигнал, который при включении может оказаться LOW. Если повесить на GPIO0 вход от оптопары, ESP32 может уйти в bootloader вместо запуска прошивки.

5. GPIO2

Для прошивки GPIO2 должен быть в корректном состоянии. Его лучше не использовать для входа, который при reset может быть жёстко подтянут к неправильному уровню.

6. GPIO12 / MTDI

GPIO12 особенно опасен: он связан с выбором напряжения flash VDD_SDIO. Если GPIO12 high при reset, ESP32 может выбрать неподходящее напряжение flash. Практический вывод: GPIO12 лучше не использовать для внешних сигналов, которые могут быть HIGH на старте.

7. GPIO15 / MTDO

GPIO15 может влиять на boot log. Если он в неправильном состоянии, может казаться, что UART лог молчит.

8. Flash/PSRAM-пины

Для ESP32:

text
GPIO6-GPIO11 - обычно SPI flash, не использовать
GPIO16/GPIO17 - могут быть заняты PSRAM на некоторых модулях

Для ESP32-WROOM-32U без PSRAM GPIO16/GPIO17 часто доступны, поэтому UART2 TX17/RX16 может быть допустим. Но при смене модуля на WROVER/PSRAM нужно перепроверить. Для ESP32-C3 GPIO12-GPIO17 часто связаны с flash.

9. UART0

GPIO1/GPIO3 обычно используются для flashing/debugging. Рекомендуемая политика:

text
UART0:
  прошивка, monitor, CLI, HIL-debug
UART2:
  EC25 modem
другие GPIO:
  входы, управление питанием, синхросигналы

10. Input-only GPIO34-GPIO39

На ESP32 GPIO34-GPIO39 - только входы. У них нет программно включаемых pull-up/pull-down. Хорошо для:

  • дискретных входов;
  • ADC;
  • сигналов состояния.

Плохо для:

  • управления реле;
  • PWRKEY/RESET EC25;
  • LED;
  • 1-Wire;
  • I2C;
  • линий, где нужна внутренняя подтяжка.

11. ADC2 и Wi-Fi

На ESP32 ADC2 конфликтует с Wi-Fi. Если Wi-Fi используется, аналоговые измерения лучше планировать на ADC1. Стартовая политика:

text
аналоговые измерения + Wi-Fi -> ADC1
ADC2 использовать только при полном понимании ограничения

12. STM32-параллель: SWD надо беречь

На STM32 похожая проблема - debug pins:

text
PA13 / SWDIO
PA14 / SWCLK
NRST
BOOT0

Рекомендации:

  • не занимать PA13/PA14 на ранней стадии;
  • вывести NRST на разъём;
  • BOOT0 не оставлять floating;
  • SWD-разъём оставить доступным.

13. Типичные ошибки

  • повесить внешний вход на GPIO0;
  • использовать GPIO12 как обычный вход с внешней подтяжкой вверх;
  • занять UART0 под рабочую периферию;
  • взять GPIO34-GPIO39 для выхода;
  • надеяться на внутреннюю подтяжку в важном сигнале;
  • использовать ADC2 вместе с Wi-Fi;
  • на STM32 отключить SWD в CubeMX.

14. Практическое задание

Создай PIN_AUDIT.md:

markdown
# Pin audit
## Target MCU/module
- MCU: ESP32-WROOM-32U
- Framework: ESP-IDF 6.x
- Board revision: ...
## Reserved / dangerous pins
### ESP32 strapping pins
- GPIO0: BOOT / download mode
- GPIO2: boot mode related
- GPIO5: strapping
- GPIO12 / MTDI: flash voltage strap
- GPIO15 / MTDO: boot log strap
Rule:
Do not connect external uncontrolled signals to strapping pins.
### Flash / PSRAM
- GPIO6-GPIO11: do not use
- GPIO16/GPIO17: check exact module
### UART0
- GPIO1 TX0: console/flashing/debug
- GPIO3 RX0: console/flashing/debug
### Input-only
- GPIO34-GPIO39: input only, no internal pull-up/down
### ADC
- Prefer ADC1 when Wi-Fi is used.
- Avoid ADC2 for measurements that must work during Wi-Fi operation.

Таблица:

markdown
| Signal | GPIO | Direction | Boot-sensitive? | Pull | Owner component | Risk | Decision |
|---|---:|---|---|---|---|---|---|
| EC25_TXD | 17 | ESP32 TX | check module | external/device | modem_service | PSRAM conflict on some modules | OK for WROOM-32U |
| EC25_RXD | 16 | ESP32 RX | check module | external/device | modem_service | PSRAM conflict on some modules | OK for WROOM-32U |
| CLI_TXD | 1 | TX | UART0 | USB-UART | cli_service | boot/debug conflict | keep |
| CLI_RXD | 3 | RX | UART0 | USB-UART | cli_service | boot/debug conflict | keep |

15. Короткий итог

Пины надо проектировать до кода. Базовая политика ESP32:

text
UART0 GPIO1/GPIO3:
  оставить для прошивки, CLI, monitor, HIL recovery.
GPIO0/GPIO2/GPIO5/GPIO12/GPIO15:
  не использовать для внешних неопределённых сигналов.
GPIO6-GPIO11:
  не использовать, flash.
GPIO34-GPIO39:
  только вход, внешние подтяжки обязательны при необходимости.
ADC:
  при Wi-Fi предпочитать ADC1.
EC25 UART:
  UART2 TX17/RX16 допустим для текущего ESP32-WROOM-32U,
  но recheck при смене модуля.
Для output выбран GPIO34 классического ESP32 из урока. Какая проверка запрещает назначение?

Задание

UART2 использует TX17/RX16 на ESP32-WROOM-32U без PSRAM. Проект меняется на PSRAM module. Что перепроверить перед повторным использованием board_pins.h?

Критерии самопроверки: Назовите module-specific memory reservations и boot/debug checks; не переносите pin map без проверки.

Показать ответ автора

Проверьте reservations Flash/PSRAM точного module, доступность GPIO16/GPIO17, boot/strapping behaviour и доступ debugging/flashing. Допустимое назначение старого module не становится автоматически допустимым для нового. Зафиксируйте module и внешние levels при reset в pin audit.