ESP-IDFを使ってみる

i2cドライバー


ESP-IDF V5.2から新しいi2cドライバー(New Driver)が導入され、今までのドライバーはLegacy Driverとなりました。
New Driverではコールバックによる非同期通信と10Bit Address(使ったことないです)がサポートされました。
同期通信のAPIも全く変わっています。

こちらがLegacy DriverでのMaster書き込みです。
START/ACK/STOPビットは全て指定する必要があります。
i2c_param_config

i2c_driver_install

i2c_cmd_link_create

i2c_master_start // Startビット

i2c_master_write_byte // i2cアドレスの指定

i2c_master_write/i2c_master_write_byte



i2c_master_write/i2c_master_write_byte

i2c_master_stop // Stopビット

i2c_master_cmd_begin

i2c_cmd_link_delete

こちらがNew DriverでのMaster書き込みです。
START/ACK/STOPビットの操作は不要になりました。
i2c_new_master_bus

i2c_master_bus_add_device

i2c_master_transmit



こちらがLegacy DriverでのMaster読み込みです。
START/ACK/NAK/STOPビットは全て指定する必要があります。
i2c_param_config

i2c_driver_install

i2c_cmd_link_create

i2c_master_start // Startビット

i2c_master_write_byte // i2cアドレスの指定

i2c_master_read/i2c_master_read_byte



i2c_master_read/i2c_master_read_byte

i2c_master_stop // Stopビット

i2c_master_cmd_begin

i2c_cmd_link_delete

こちらがNew DriverでのMaster書き込みです。
START/ACK/NAK/STOPビットの操作は不要になりました。
i2c_new_master_bus

i2c_master_bus_add_device

i2c_master_receive



こちらがLegacy DriverでのProbe(デバイスの検出)です。
i2c_param_config

i2c_driver_install

i2c_cmd_link_create

i2c_master_start // Startビット

i2c_master_write_byte // i2cアドレスの指定

i2c_master_stop // Stopビット

i2c_master_cmd_begin // デバイスが存在するときはESP_OK

i2c_cmd_link_delete

こちらがNew DriverでのProbeです。
i2c_new_master_bus

i2c_master_bus_add_device

i2c_master_probe // デバイスが存在するときはESP_OK



新旧ドライバーのパフォーマンスを測定してみました。、
IO Expanderとしてよく使われるMCP23017を使い、以下のテスト回路でGPA0のポートを10000回ON/OFFするのに必要な時間を計測し ました。
ソースはこち らで公開しています。

こちらが各SoCの結果です。
いずれのSoCでも、New Driverの方が30%程度、高速に動作します。
ESP32のi2cドライバーではI2C Clock周波数の最大値は1.0MHzとなっていますが、ESP32C2、C3、H2では1MHzでは正常に動きません。

I2C Clock周波数[MHz]
Legacy Driver[ミリ秒]
New Driver[ミリ秒]
esp32@160 1.0 9420 6540
esp32@240 1.0 7060 5290
esp32s2@160 1.0 7420 4450
esp32s2@240 1.0 5790 3830
esp32s3@160 1.0 8700 5240
esp32s3@240 1.0 6720 4450
esp32c2@120 0.6 8890 5520
esp32c3@160 0.9 6550 3880
esp32c6@160 1.0 6490 3850
esp32h2@96 0.8 10150 5430

グラフにしてみました。
こちらがCPUクロックが160MHz(一部のSoCでは120MHzや96MHz)の時のグラフです。
僅差ですが、ESP32C6が一番早い結果となりました。


こちらがCPUクロックが240MHzの時のグラフです。
少し意外ですが、ESP32S2が一番早い結果となりました。


こちらがSoC毎のLegacyドライバーの結果です。


こちらがSoC毎のNewドライバーの結果です。
CPU周波数の低いESP32C3/C6が頑張っています。




1つのプロジェクトで、LegacyドライバーとNewドライバーを使い別ける場合、CMakeLists.txtでESP-IDFのバージョン を判断して、
リンクするソースを切り替えることができます。
このテクニックはこ ちらのプロジェクトで使われています。
# get IDF version for comparison
set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}")

set(component_srcs "main.c")

if(idf_version VERSION_GREATER_EQUAL "5.2")
    list(APPEND component_srcs "ssd1306_i2c_new.c")
else()
    list(APPEND component_srcs "ssd1306_i2c_legacy.c")
endif()

idf_component_register(SRCS "${component_srcs}"
                       PRIV_REQUIRES driver
                       INCLUDE_DIRS ".")

続く....