RZ/A2M のDMACについて教えてください

はじめまして、JiGoRoです。

RZ/A2M Application Package v2 リリースありがとうございます。

FreeRTOSを使う上で、ペリフェラル、特に通信における割り込み発生頻度を下げたいので、DMAとの組み合わせを考えてます。

(現在、ハードウェアを開発中で、並行してソフト構想設計を行っております)

RX系マイコンは良く使っているのですが、RZマイコンは初めてなので、質問させてください(初歩的な質問で申し訳ございません)。

 

DMAの転送トリガーをSCI(SCIFAではない方です)の送信割り込みとした場合、

① DMAの指定回数の転送中は、SCIの送信完了割り込みは発生しない、という認識で正しいでしょうか?

② DMAの指定回数転送完了後、最後の1バイトを送信し終わったタイミングでは、SCIの転送完了割り込みは発生する、という認識で正しいでしょうか?

 

想定アプリは、半2重式のUART伝送を行うものです。 転送終了後、受信体制で待たせたい、と考えてます。

そのため、DMA転送中、後の送信完了割り込みの考え方を整理しておきたいと思いまして、質問させて頂きました。

 

よろしくお願い致します。

 

  • JiGoRo です。 たびたび失礼いたします。
    Smart Configulator SCIFA driver v.2.00 でテストしてます。
    DMACを使うとき、悩んでいた点が大きく勘違いしていたみたいです。
    ポイントは、送信データを write() 前で配列を生成し、DMA転送付きで SCIFAn から送信しようとしたとき、CPUで創りこんだデータ配列がキャッシュに溜まっているため、DMA転送によるデータでは期待した配列になっていないということだったようです。
    試しに、const uint8_t foo[64]={1,2,3,...64}; といった配列を用意しておいて、Smart Configulator や open, write関数など変更なく foo データを送ると正しく送信されますが、volatile uint8_t baa[64]; として、write() 前に baa[0]=1; baa[1]=2; ... などと記載し、write() しても、baa[]にもともとあったデータが吐き出されました。(0が出てきました)。
    サンプルコードに read() 後に L1キャッシュを操作するAPI として R_CACHE_L1DataInvalidLine()があるので、これを write()前に実施してみればよいのかな?と思って試しましたが、依然変わらず、生成した配列のデータが出てきません。
    どのようにするのがあるべきコードなのか、ご教授いただきたいです。
    よろしくお願いいたします。
  • JiGoRo です。 自己レスします。
    MMUにて InternalRAMエリア (0x80000000)を Normal(Non-cacheable) としたら所望のデータが出力されました。インターナルRAMなので、キャッシュ効かせなくても高速に動いてくれそうなので、当面はこれで良しかな?と。 デフォルトが L1 cacheable なので、ちょこっと注意かな?と。 これすれば、read 後も internal RAMエリアであれば、R_CACHE_L1DataInvaridLine()は不要になりますね(当たり前といえば、当たり前ですが)。
    ようやく、半2重通信のコードが完成しそうです。。。長かった~
  • わわいです
    DMAってのは、ハードウエアでメモリのデータを読み出してくるため、キャッシュをONにすると、キャッシュしているデータは読みだせず、メモリ上に展開されているデータを読んでくるため、違う結果となってしまいます。
    そのため、RZでは、キャッシュをOFFとした領域に対してDMAを行う必要があります

    #DMAのパラメータの中でキャッシュメモリにどーこーってあるんですが、そこまで追求してません
  • JiGoRoです。 たびたびすみません。 DMAC関係で質問です。
    うまく動かないなぁ、と悩んでいて1つのことに気が付きました。
    Software Package v6 の DMAC+SCIFAのサンプルコードを使っても再現できます。
    前提:
    ・SCIFA2 と SCIFA3 を DMAC の送受信対象と設定します。
     (それぞれDMACは別のものであり、callback関数なども独立して1つずつ作っています)
    ・SCIFA2 に対して write() にて転送を開始します。
    (ループ位置)
    ・SCIFA2 DMAC終了のタイミングで callback関数にて終了フラグを立てます。
    ・SCIFA2 のDMAC終了フラグを検出した後に、SCIFA3 に対して write() にて転送を開始します。
    ・SCIFA3 DMAC終了のタイミングで callback関数にて終了フラグを立てます。
    ・SCIFA3 のDMAC終了フラグを検出した後に、 SICAF2 に対して write() にて転送を開始します。
     以降、ループ位置まで戻り、繰り返します。

    結果:
    ・DMACによる SCIFAn 転送がうまく動作しません(受信側にデータが届きません)。
     SCIFA2とSCIFA3を単独でDMAC使う場合は、問題なく繰り替えし転送確認できます。
     また、DMACを用いない場合も、問題なく繰り返し転送確認できております。
    ・1つのDMAC+SCIFA(2or3)と、DMACを使わない SCIFA4 に対して送受信を行うと、
     正しく送受信されます。

    疑問点:
    ・SCIFAn の転送をDMACで行う場合、DMAC終了のタイミングで別のDMAC+SCIFAn を動かすためには、何かRZ/A2MのSFRチェックをしないといけないのでしょうか?
    (所感:SCIFAn の転送を DMACで行い、DMAC転送終了時は、SCIFAn のFIFOには送信待ちデータが残っているので、同じSCIFAn に対して送信する場合は気を付けないといけないのかな?とは思いますが、別のDMAC+SCIFAn なので、極論転送終了を待たずとも、write() しても良いように思います)

    なお、サンプルコードでは、SCIFA2 を loopback test モードでコンソールに対して入出力させていますが、SCIFA3 は実周辺機能設定を行い、競合しないようにしています。 更に、loopback test モードを外し、SCIFA2 を実周辺機能に設定しても、転送の確認ができません。