DMAを使用したUART受信について

毎度お世話になっております。

V850ES/JH3-Eを使用しております。

DMA0の転送起動要因としてUARTC3の受信完了割り込み(INTUC3R)を指定しています。

例えば、DMA0の転送回数を5回、5バイトの受信があった場合、最初の1バイトを受信した時点でDMA0が転送を開始し、その後の4バイトで起こる受信割込みは無視される、という認識で正しいでしょうか。

また、このとき無視される受信割込みの割り込み要求フラグ(UC3RIF)は、DMA転送完了割り込み内でクリアする必要があるのでしょうか。

あと、通信速度が遅い場合、UARTC0の受信レジスタが更新されていないのにDMA0がデータの取得に行ってしまう、ということは起こりうるのでしょうか。

毎度質問ばかりで申し訳ありませんが、
以上、よろしくお願いいたします。
  • dai_toryさん

    DMA転送の前に…UARTCの受信完了割り込みは1フレーム(スタートビット+データビット{8bit or 7bit}+パリティビット+ストップビット)ごとに発生するので、DMA転送トリガにUARTCを指定する場合は、転送回数は基本的に1回となります。

    複数回指定した場合、同じ転送を繰り返し、バス権を占有するため非効率となります。また、転送元、転送先アドレスの設定によっては(データ上書きによる)不具合の原因となります。

    この場合の設定は、転送元:ソースアドレスを受信レジスタ(UC3RX、アドレス固定)、転送先:デスティネーションアドレスをRAM(アドレスインクリメント、もしくは固定)にしておき、DMA転送を行います。転送完了後、DMA転送完了割り込みが発生するので、必要に応じて次の転送アドレスをセットします。


    一方、UARTC受信割り込みでは割り込みが管理するバッファに蓄積しておき、伝文単位の取得を認識した時(CRやLFを受信したなど)にDMAでアプリケーション領域に転送をしたい場合は、転送元をバッファアドレス(インクリメント)、転送先をアプリ領域アドレス(インクリメント)にして、転送回数を受信したバイト数と、ソフトウェアからDMAを起動すれば一括でRAMに転送できます。

    一括転送を行う場合、UARTC受信割り込み内で行うと割り込み処理の時間が長くなってしまう恐れがあるので、伝文単位の受信が完了したかを非割り込み処理中にポーリング確認し、必要に応じてDMA転送したほうがより安全かと思います。
    しかしながら、こちらの場合はDMAの恩恵に与っているのかイマイチ疑問ではありますが…
  • スタッフのチョコです。

    dai_tory様の質問に回答させていただきます。

    V850ES/JH3-EのDMAコントローラは1回のDMA転送要求で,1回の転送を行ったら,バスを解放します。その後DMA要求があれば,再度DMA転送を行います。

    また,UARTC3の受信完了割り込みをDMA起動要因に設定された場合,UARTC3は受信完了により通常の割り込み要求とDMA転送要求を同時に発生させます。つまり,DMA転送要求と割り込み要求が同時に発生してしまいます。

    そのため,DMA転送を使用する場合には,UARTC3の割り込み要求をマスク(UC3RMK=1;)しておく必要があります。UARTC3の(通常の)割り込み要求はマスクしたことで,ペンディングされた状態になっていますから,指定回数のDMA転送が完了してDMA転送完了の割り込みの中でUARTC3の割り込み要求フラグをクリア(UC3RIF=0;)してください。(なお,UARTC3の割り込みを全く使用しないのであれば,UC3RMK=1に設定したままでUC3RIFを無視しても問題はありません。)

    DMAはUARTC3の受信完了割り込みでDMA転送を開始し,転送完了後にバスを解放して,DMA転送要求があるかを確認します。この時点ではUARTC3では次のデータの受信は完了していないので転送要求は発生していないため,DMAは起動しません。
    つまり,DMAの転送回数を5回に設定しておくと,UARTC3での受信完了ごとに5回のDMA転送が行われます。ご心配されている,UARTC3の受信データが更新されていないのにDMAが転送を行うことはありません。


  • SHの場合は、SCIのみの割り込みでプログラムを作成しておいて、DMAの設定を追加することでSCIの割り込み許可設定を修正しなくても上手く動作できます。チョコさんの書き込みからV850の場合はDMAの設定追加だけではSCIからCPUの割り込みは残ってしまうためSCIの設定変更も必要になるとの理解で良いでしょうか?

    ここからはマト外れの可能性もありますが、ご愛嬌でお許しください。
    dai_toryさんがどこでDMAを起動しているかが気になります。1バイト目の受信完了時にDMAによる4バイト分の転送を起動しているようにも予想されます。プログラムの初期化でDMAを初期化起動しておけば、SCIからCPUへの割り込みは全くかからなくなります。指定したイベントで指定されたサイズ分の転送が実行されるので先取りすることはありません。DMAの割り込みを許可しておいて指定回数分の転送が完了すると、DMAからCPUに割り込みが発生して、DMAを再設定・再起動が一般的に思えます。ここまでは、すとさんの説明の一部の繰り返しと思ってます。
    もしかすると、、、。通信は非同期システム間で実行されるので一貫性のあるかたまりの先頭バイトを見つけてデータを取り込むような処理が必要になります。SCIの割り込みで先頭バイトの判断をしてからDMAで残りを転送を実施しているならば、3かたまり分(15バイト)以上のリングバッファを用意しておいて、とりあえずSCIからのデータを取り込んで、必要なときに最新のまとまったデータを読み出すのが良いと思います。UARTBなら2かたまり以上の16バイトのFIFOがあるからリングバッファやDMA無しで行けそうですね。
  • すと様
    チョコ様

    返信が遅くなり申し訳ありません。

    「その後の4バイトで起こる受信割込みは無視される」という認識が間違っていたこと、理解できました。
    検証コードも作成して動作していることを確認しているのですが、上記のような認識でしたので疑問に思った次第です。

    また、すと様にご指摘いただいたDMAのバス占有も確認してみました。
    今回の場合のバス占有時間は以下のようになるかと思います。
    9クロック = 2(内蔵RAM) + 1(idle) + (3(UC3RX) + 3(VSWC=0x12で設定したウェイト))
    DMAを使用せず普通に受信完了割り込みを処理する場合のCPU時間と、バス占有時間とを天秤にかけると、今回はDMAを使用したほうが効率が良さそうです。

    お二人の丁寧なご説明に感謝いたします。
    ありがとうございました。
  • スタッフのチョコです。

    kijo様の質問にお答えいたします。

    V850でDMA転送を使う時には周辺機能(この場合はUARTC3)の割り込み要求をマスクしておく必要があります。
    DMA転送だけで,それ以外に割り込み機能を使用しないなら,初期設定で割り込み要求のマスクを解除しないだけです。(割り込みマスクレジスタはディフォルトではマスクが設定されています。)
    DMA転送だけでなく,割り込みと使い分ける場合には,割り込みを使う直前に,割り込み要求フラグをクリアし,マスクを解除します。DMA転送を使う直前に割り込みマスクを設定します。

    なお,これらは割り込みコントローラでの設定で,周辺機能側での設定変更ではありません。



  • ご教授ありがとうございます。V850SFx3\,V850SEKG2\,V850IG3に可能性あったのでマニュアを読んだ事があったのですが、紙だけだとわかった気になってしまいます。