Open5

ESP32用Rustについてのメモ

tanatana

ESP-IDFの各機能を使うためのライブラリはいくつかのクレートに分かれている。

  • esp-idf-hal: GPIOやADCなどのペリフェラル、delayなどの基本機能。
    • embedded-hal(マイコンの種類を問わない標準化されたAPI)に準拠している
  • esp-idf-svc: 無線通信など
    • WiFiの管理(モード変更、アクセスポイントへの接続など)はここ
    • タイマなどに対する高水準なAPIや、ロギングなどの便利な機能も含まれている
  • esp-idf-sys: ESP-IDFのC関数をほぼそのままラップしたもの
    • ESP-IDF特有のビルド時処理などもここに含まれる
    • 直接esp_idf_sys::以下の関数を呼ぶことはなくても、必ず必要になる極めて重要なクレート。
  • Rust標準ライブラリ(std::以下): PCではOSが提供するような機能(コンソールやスレッドなど)
    • ソケット通信はここ(標準のstd::netを使用)
    • ESP-IDF向けの実装は主に、esp-rs/rustのUNIX向けstd実装の中に、#[cfg(target_os = "espidf")]の条件コンパイルで作られている。
tanatana

特別な設定をしなければmain関数はCore 0で動く。
Core 1にするにはsdkconfig.defaultsファイルにCONFIG_ESP_MAIN_TASK_AFFINITY_CPU1=yを追加(ESP-IDFと同じ)。

tanatana

マルチタスクにはRust標準のstd::threadを使う。これはUNIX系OSと同様のPOSIX Thread APIで実装されているが、実際にはFreeRTOS関数をラップしたもの

優先度の設定や特定コアへの固定などはesp_idf_hal::task::thread::ThreadSpawnConfigurationを使う。
これに値を設定してsetを呼ぶことでesp_pthread_set_cfgが呼ばれ、その後作られるPOSIX Threadの設定を変えることができる。
ただしFreeRTOSタスクの名前(ThreadSpawnConfigurationnameフィールド)はC文字列(NULL終端)なので、次のように初期化する必要あり(once_cell使用)。

use once_cell::sync::Lazy;
use std::ffi::CString;
static TASK_NAME: Lazy<CString> = Lazy::new(|| CString::new("foo").unwrap());

fn main() {
  ...
  ThreadSpawnConfiguration {
        name: Some(TASK_NAME.as_bytes_with_nul()),
        priority: 2,
        ..Default::default()
    }
  ...
}
tanatana

esp_idf_sys::log::EspLogger::initialize_default関数を呼ぶと、logクレートのマクロ(info!warn!など)でログが出せるようになる。
これはESP-IDFのロギングシステムを利用しているので、CのESP_LOGI等と同様のログレベル分類があり、時間やモジュール名もつく。