ESP32 で SPI スレーブ通信するときの注意点

組み込み
スポンサーリンク

EPS32 で SPI のスレーブ通信を行う方法とと注意点を紹介します.

スポンサーリンク

はじめに

ESP32 の SPI サンプルはいろいろありますが,どれも ESP32 がマスターになるもので,スレーブになるサンプルがなかったので紹介します.

次の観点に留意して記述しています.

  • 利用者が多くて馴染みやすい,Aruduino を前提にすること
  • CPU に負担を与えない,DMA の使用前提にすること
  • 簡単に動作確認できるよう,SPI 通信のマスターとスレーブを同じ ESP32 で動かすこと

コード

ESP32 は SPI 全二重通信用のペリフェラルとして VSPI と HSPI の2つを内蔵していますが,今回は VSPI をマスター用に,HSPI をスレーブ用に使いました.

スレーブ側の処理の流れは次のようになります.

  1. バスを spi_slave_initialize で初期化.
  2. spi_slave_queue_trans で送信データをセット.
  3. マスターが通信を行うと,spi_slave_interface_config_tpost_trans_cb に指定したコールバック関数が呼ばれる.
  4. 必要に応じて,受信値の読出しや次回の通信用の送信データのセットを行う.
  5. 3. に戻る.(次回通信用の送信データをセットした場合)

コード全体は下記のようになります.

マスターとスレーブの端子をジャンパで接続すれば,1秒ごとに通信を行います.使用端子は VSPI と HSPI のデフォルトのものを使用しています.具体的な番号はソース参照.

注意点

実は,上記を実行すると下記のような出力がされます.スレーブが末尾の 4Byte を受信できていません.

これは既知の問題のようで,公式フォーラムにも以下のやりとりがあります.シリコン修正しないと直らないようです.

SPI slave driver, last 4 Bytes missing (using DMA)
https://www.esp32.com/viewtopic.php?f=12&t=7339&sid=2257561718efae97d5b805c039b5764e&start=10

対策としては,以下のいずれかの方法があります.

  • 4Byte 分余分に通信を行う
  • spi_slave_initialize の最後の引数を 0 にして,DMA を使わないようにする

ただし,後者の場合,最大転送サイズは64Byteとなりますので,制約が大きいです.それより大きいサイズを指定すると次のようなエラーがでます.

余談

今まで,ESP32 を Arduino から使う場合,Arduino IDE を使っていたのですが,最近は Visual Studio Code (VSCode)に PlatformIO を入れたものを愛用しています.

PlatformIO には ESP32 の製造元もコミットしているので,ボタンクリックだけで導入できるので楽です.さらに VSCode だと Arduino IDE にはない補完やタグジャンプが設定なしで有効になるので,初めて使うライブラリでもサクサク記述できます.

おすすめです.

コメント

  1. motimotiko より:

    SPI_MODE0 か SPI_MODE2であれば現象は確認されないようです。

  2. Ninagawa より:

    詳細な記事をありがとうございました!こちらの記事を参考に手元でも動かしてみましたので、その時のメモをQiitaにまとめさせていただきました。