ESP32-S3 + MicroPythonでGPIO19とGPIO20のピン割込を使いたい場合


この記事のあらすじはこうである。

「ESP32-S3 + MicroPythonでGPIO19とGPIO20のピン割込が使えないと思ったら、それぞれUSB_D-とUSB_D+に割り当てられている関係でピン割込が無効になっている。USBを無効化したカスタムファームウェアをビルドして焼いたら使えるようになった」

ISRが呼ばれない

GPIO19とGPIO20はデフォルトの機能がそれぞれUSB_D-とUSB_D+となっているが、GPIOとしてRead & Writeは普通に使える。ただし、ピン割込みが使えない。こんな感じで

pin = Pin(19, Pin.IN, Pin.PULL_UP)
pin.irq(handler=handler_func, trigger=Pin.IRQ_FALLING)

GPIO19をHIGH→LOWにしても割込ハンドラは呼ばれない。エラーも出ない。

ファームウェアのソースを読む

ここでファームウェアのソースを読んでみる。ESP32のGPIO周りを実装している ports/esp32/machine_pin.c にこんなことが書いてある。

#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
(中略)
#if CONFIG_USB_CDC_ENABLED
{{NULL}, -1}, // 19 is for native USB D-
{{NULL}, -1}, // 20 is for native USB D-
#else
{{&machine_pin_irq_type}, GPIO_NUM_19},
{{&machine_pin_irq_type}, GPIO_NUM_20},
#endif
(中略)
#endif

USB_CDCを有効にしてビルドするとGPIO19とGPIO20の割込みが無効化されるようになっている。

USBを無効にしてファームウェアをビルドする

「USBは使えなくていいからGPIO19と20でピン割込を使わせてよ!」という場合どうするか。まず、どこでUSBを有効化しているかというと、ports/esp32/boards/sdkconfig.usb

CONFIG_USB_ENABLED=y
CONFIG_USB_CDC_ENABLED=y
CONFIG_USB_CDC_RX_BUFSIZE=256
CONFIG_USB_CDC_TX_BUFSIZE=256

と記述されており、これを各ボードのmpconfigboard.cmakeで取り込んでいる。たとえばGENERIC_S3mpconfigboard.cmake

set(IDF_TARGET esp32s3)

set(SDKCONFIG_DEFAULTS
    boards/sdkconfig.base
    boards/sdkconfig.usb
    boards/sdkconfig.ble
    boards/GENERIC_S3/sdkconfig.board
)

となっている。boards/sdkconfig.usb という行を入れなければUSBは無効化され、GPIO19と20でピン割込も使えるようになる。