変更が完了したので公開。
PlatformIO用のライブラリ化したもの(2021/08/09追記)
秋月のプログラムから変更した内容は以下の通り。
- Arduino系APIを取り除き、ESP-IDFでビルド可能なものにした。
- SPI送信の高速化を実施。
秋月のプログラムにライセンスの記載がなかったので、とりあえずMITライセンスにしておいた。
問題があれば修正する予定。
SPI送信部分について
今までのまとめみたいなものなのだが、以下のような感じになっている。
- ESP32 APIを使った実装になっている。
- キュー形式+DMA転送を使い、CPU処理のバックグラウンドでSPIの転送処理を行うようにしている。(たぶん)
キュー形式での送信について
spi_transaction_tにデータを詰めてspi_device_queue_transでデータを送信することで実現している。
spi_transaction_tのデータは、begin()内でメモリ確保しておき、それをリングバッファ的に使うことでspi_device_queue_transからspi_device_get_trans_resultでデータを受け取るまでの期間データが変更されることがないようにしてある。
データを変更してはいけないことについて、spi_device_get_trans_resultのAPIの説明に以下の様に書かれている。
It will then return the description of the completed transaction so software can inspect the result and e.g. free the memory or re-use the buffers.
当初、これが何を言っているのかわからず、spi_device_queue_transの中で設定されたデータがが別確保されていると思っていたのだが、謎のヒープエラーが出ることになってしまった。
上の内容は、spi_transaction_t.tx_bufferの内容にも当てはまり、4バイト以下のデータの場合、tx_data側に詰めなおしたほうがいいとも記載があった。
DMAを使ったデータ転送
spi_transaction_t.tx_bufferの領域に関しては、MALLOC_CAP_DMAで確保した領域を使用している。
実際にDMA転送の指定は、spi_bus_initializeの最後の引数でどのDMAチャンネルを使うか指定するとのこと。
送信時の状態
今回の処理を行った結果、BOXを塗りつぶし描画データを送信した場合の信号の状況は以下の様になった。
1段目がMOSI、2段目がCLK、3段目がCS、4段目がDCになっていて、5段目(最下段)はロジックアナライザで状態の解析がしやすいように、spi_device_get_trans_resultで結果を取得しているときをHighにするようにしたデバッグ用の情報になる。
黄色の線の区間がsetWindow関数内で0x2A,0x2B,0x2Cまでの各コマンドをキューに入れ、それを送信している期間、赤色は色データを連続送信している期間になる。
これを見る限り、色データを作成するよりデータの送信の方が時間がかかっていることが分かる。
下段右側の黄色丸部分で、Hの状態が維持されていてspi_device_get_trans_resultのリターン待ちになっているため。
上の図は解析しやすいようにSPI周波数を1MHzにしているのだが、最速の40MHzにしても転送の待ち時間はあるようだったのでCPUを効率よく使う場合には、転送のタイミングとか、処理単位とかいろいろ考える必要があるかもしれない。
コメント