📘

TinyGo + Wio Terminal で DMA を使い、高速で データ転送 + SPI 送信をしてみる

に公開
2025/12/23

この記事は TinyGo Advent Calendar 2025 21日目の記事です。

結論

DMA のサンプルコードを作成し、DMA の有無の動作を比較することができました。

背景

実施しようと思った理由は、以下。

  • TinyGo本 の column に LCD の描画は DMA を使うともっと高速化できると記載されていて、いつかやってみたかったため
  • DMA 自体、知識としては知っていたが、使うことは無かったので、やってみたいと思ったため

環境

  • PC
    • Windows 11
  • TinyGo/Go
    • tinygo version 0.39.0 windows/amd64 (using go version go1.24.5 and LLVM version 19.1.2)
  • デバイス
    • Wio Terminal

タスクリスト

  • DMA の仕様確認
    • DMA のライブラリの処理確認
      • examplesを動かして、ある程度確認済
    • DMAの仕様についてまとめる
      • 一般的な話は別記事参照とし、主にライブラリの処理についての説明をまとめる
    • SPI Tx サンプルを作って、DMAの有無による差を確認する
      • 送信に掛かる時間を測定する
        • DMA を使用している方が短い時間になっていることを確認した
      • ロジアナでSPI通信の波形を観測する
        • DMAを使用している方が、通信の間隔の幅が狭いことを確認した

タスクの詳細

DMA のライブラリの処理確認

使用したライブラリはこちら。

注意点として、上記は feather-m4 用の物であり、Wio Terminal では上手く動かないところがありました。
例として、SPI0 が参照している sercom が違うようでした。

DMAの仕様についてまとめる

一般的な情報

DMA は簡単に言うと、CPU を介さずにデータを転送する仕組みです。CPU を介さないので、CPU の負荷を下げ、転送速度を上げることができます。
DMA の仕様について、一般的な情報としては他の人が情報がまとめられているので、そちらが参考になります。

今回使用する DMA の情報

一般的な情報は↑の通りなので、DMA ライブラリを観つつ、Wio Terminal に搭載されている atsamd51p19a の DMA の使用方法を記載します。
DMA には Descriptor という DMA の設定を複数作成できるようになっています。↓のような感じです。

  • トリガー
    • SPI 送信完了、タイマー等いろいろなものをトリガーにして転送することができます
  • DMA転送時の動き
    • 1Byte ずつ転送するか、複数Byte(ブロック)で転送するか等を選ぶことができます
  • インクリメントするか
    • 例:メモリ→メモリへの転送
      • どちらもインクリメントしないとずっと同じアドレスを参照して読み書きしてしまいます
    • 例:メモリ→シリアルデータ送信用のレジスタへの転送
      • レジスタ側のアドレスはインクリメントしたくないので SRCをインクリメントし、DST はインクリメントしないという設定になります

補足:他にも色々設定がありますが、長くなるので省略しています。

SPI Tx サンプルを作って、DMAの有無による差を確認する

作成したサンプルコード

作成したサンプルコードは以下。

補足:SPI 送信する1回のデータ量は 320*240byte(Wio Terminal の画面の Pixel数) で実験しています。
しかし実施には、1Pixel あたり 2byte 送信する必要があるので、上記の2倍のデータを送信する必要があります。

実行時間

1画面分のデータの送信時間。

  • DMA無し
    • 1552001 us
  • DMA有り
    • 227050 us

波形

  • DMA無し
    • 1画面分のデータの送信間隔は 24 us
  • DMA有り
    • 1画面分のデータの送信間隔は 2 us

その他

Wio Terminal の LCD に表示する際、DMA を使ってみたいと思いチャレンジしていますが、現在苦戦中です・・・。

Discussion