UARTの受信DMA処理の定石


SPIマスタ等の自分からクロックを出力する通信の場合は、何バイト受信するかを自分で把握できているのでDMAを仕掛けるのは簡単ですが、UARTの場合、非同期でいつ来るかわからないデータを待ち受けてるのが普通だと思います。

いつ受信するかわからない。何バイト受信するかわからない、という状況なので、指定回数受信したらDMA割込み、というシンプルな使い方ができず、実装をどうすればいいのか悩んでいます。

パッと思いついたのは、下記で示しているように、贅沢にもバッファを3本用意して、周期的にDMAバッファを切り替えるという方法です。

[code]

    for (;;)
    {
        メインループ処理;
    
        if (前回の処理から適当な期間が経過した)
        {
            int count; // DMAカウンタ
            int prev;
            UART割込み無効;
                count = getDMACount();
                prev = index;
                index ^= 1;   // DMAバッファインデックスの切替
                // この区間で他の割込み処理が入るとオーバーランが発生しそうなので全割込み禁
                // 止にしておいた方がよい？
                setDMABuffer(duble_buffer[index]);
            UART割込み有効;
    
            if (count > 0)
            {
                // ダブルバッファとは別に用意したメインのバッファの末尾にコピーする。
                memcpy(main_buffer + last, duble_buffer[prev], count);
                last += count;
            }
        }
    }
    
[/code]

こういう処理ってほとんどやることは決まっていると思うので、定石みたいな実装があると思うのですが、何か実装の参考になる文献や入手可能なソースコードはないでしょうか。Linuxカーネルのソースもちょっと覗いてみましたが、該当しそうな部分が見つけれらませんでした。




以下オイラの私見です。期待している回答とは異なるかもしれません。

オイラは２０年以上マイコンプログラムを書いている身ですが、シリアル通信の受信側で DMA を使ったことは数えるほどしかないです。

他機器や同一機器内別マイコンとの通信をする機会はよくありますが、原理的に「通信はエラーがありうるもの」です (エラー発生確率は ppm オーダーだったり
ppb オーダーだったりしますが) 可能性は低くても対処しないわけにはいかないので、エラー発生時に「途中でやめるには別手続きが必要な DMA
」は使い勝手が悪いのです。

USB の Isochronous 通信など  
\- Transaction のエラー検出・訂正はハードウエア側が勝手にやってくれる  
\- Transaction 成功時には事前に決めたバイト数が必ず得られる  
\- Transaction 失敗時にマイコンソフトが何かする必要が一切ない  
ような案件以外では DMA 使ったことないです。

定石があるとしたら、すでに質問中に書かれている通り、  
\- 定期的に、事前に決めた固定バイト長の通信がある場合に、限定的に DMA を使う  
くらいでしょうか？  
それ以外では（特に受信側で） UART 関連で DMA を使うことはまず _ない_ です。

「使わないのが定石」なのだと、オイラ個人的には思います。




以下オイラの私見です。期待している回答とは異なるかもしれません。

オイラは２０年以上マイコンプログラムを書いている身ですが、シリアル通信の受信側で DMA を使ったことは数えるほどしかないです。

他機器や同一機器内別マイコンとの通信をする機会はよくありますが、原理的に「通信はエラーがありうるもの」です (エラー発生確率は ppm オーダーだったり
ppb オーダーだったりしますが) 可能性は低くても対処しないわけにはいかないので、エラー発生時に「途中でやめるには別手続きが必要な DMA
」は使い勝手が悪いのです。

USB の Isochronous 通信など  
\- Transaction のエラー検出・訂正はハードウエア側が勝手にやってくれる  
\- Transaction 成功時には事前に決めたバイト数が必ず得られる  
\- Transaction 失敗時にマイコンソフトが何かする必要が一切ない  
ような案件以外では DMA 使ったことないです。

定石があるとしたら、すでに質問中に書かれている通り、  
\- 定期的に、事前に決めた固定バイト長の通信がある場合に、限定的に DMA を使う  
くらいでしょうか？  
それ以外では（特に受信側で） UART 関連で DMA を使うことはまず _ない_ です。

「使わないのが定石」なのだと、オイラ個人的には思います。

