R8C UART0 オーバーランエラーの原因

R8C/M36シリーズで、UART0を使用して、RS232C通信を行っていますが、たまにオーバーランエラーが発生します。

メインクロックは20MHzで、ボーレートは115200bpsです。

受信データの取込は、以下の割込み関数内で行っています

割り込みを処理を行う前、またはデータ読み込み前に何か設定することはあるのでしょうか?

また、通信速度が速いとオーバーランエラーは、まれに発生することはあるのでしょうか?

だれか教えてください。

//割り込みは常に許可

#pragma interrupt _uart0_receive(vect=18)
void _uart0_receive(void){

  bRecvData.word = u0rb; //受信データ読み込み

 if( bRecvData.byte.high & 0xF0){

      //エラー判定  エラー状態の場合は、必ずオーバーランエラーのフラグが立っている。

  }

}

Parents
  • 115200bpsではデータ受信の間隔が最短で86μ秒とかになるので、他の割り込み処理とかでちょっと割り込み禁止期間が長かったりするとわりあい簡単にオーバランエラーは起きる気はしますね。86μ秒の2倍の期間割り込みが受け付けられないとアウトかな。

  • Kirinさん

    受信割込み内での多重割込み禁止設定は

    #pragma interrupt _uart0_receive(vect=18)

    void _uart0_receive(void){

    _asm(" FCLR I");

     bRecvData.word = u0rb; //受信データ読み込み

     if( bRecvData.byte.high & 0xF0){

         //エラー判定  エラー状態の場合は、必ずオーバーランエラーのフラグが立っている。

      }

    _asm(" FSET I");

    }

    で設定すればよろしいのでしょうか

Reply
  • Kirinさん

    受信割込み内での多重割込み禁止設定は

    #pragma interrupt _uart0_receive(vect=18)

    void _uart0_receive(void){

    _asm(" FCLR I");

     bRecvData.word = u0rb; //受信データ読み込み

     if( bRecvData.byte.high & 0xF0){

         //エラー判定  エラー状態の場合は、必ずオーバーランエラーのフラグが立っている。

      }

    _asm(" FSET I");

    }

    で設定すればよろしいのでしょうか

Children
  • bosssaさん

    #pragma interruptに/Eオプションがついていないので、UART0は既に多重割り込み禁止状態ではないですか?(R8Cは割り込みを受け付けるとIフラグが”0”になって割り込み禁止状態になる仕様)

    もし多重割り込みが許可されているとした場合、そのコードでOKです。(すぐにUART0_receive関数を抜けるので後ろのFSET Iは無くても良いと思います)

    R8Cで良くあることですが、CPUクロックの分周設定を1分周にされていますか?

    CM06ビットはリセット後、”1”(8分周)になっています。

    低速オンチップオシレータからメインクロックへ切り替えれているようなので設定できていると思われますが確認してみてください。

  • 現在のところ、割り込み処理内に_asm(" FCLR I");に入れても、割り込みの優先順位も最大にして、他の割込み処理を下げてもオーバーランエラーは発生します、

    発振は、XIN-XOUTの外部発振子を使用しており、分周ないでCM06は0です。

     現状のところ、解決策がありません。何かわかることがあれば、教えてください。

  • 割り込み処理内に asm(" FCLR I"); を入れても割り込み受付で禁止された割り込みが禁止される(→要は効果なし)だけでは?

  • bosssaさん

    みなさんのご指摘どおり、受信割り込みには/Eをつけず、かつ割り込み内でもIフラグの操作をしなければOKです。(FCLR,FSETは不要)

    逆に受信割り込み以外の割り込みに/Eをつけてください。(/Eつければ多重割り込み許可になるので、改めてFSETしなくてもOK)
    #pragma INTERRUPT /E i_func

    これでどんな状態でも、受信が来たら最高優先順位の受信割り込みに飛べるので、オーバーランしなくなるはずです。
  • /E  の代わりに、#pragma INTERRUPT /B i_func にして、割り込み処理を速くして行っていますが、現在のところ一度もオーバーランエラーは発生していません。 /Bにすることで、なにか他に影響するようなことがありますでしょうか

  • 私も通信受信割り込みは/Bを付けていますが、

    まずは1バイトずつ送信して、本当にオーバーランなのかどうか調べた方がよくないですか?

    余裕が少ないと、通信以外の場所で一切割り込み禁止区間を作れなったり

    他の割り込みがあると通信を落としたりしかねないので、危険な気がします。

    多重割り込みはできれば回避したい性格なので。

  • bosssaさん

    もしかして、受信割り込み処理自体が1バイト分のデータ転送時間よりも長いというオチなのかもしれません。
    バンク切り替えによって少し高速化したおかげでギリギリ間に合っているのかもしれませんね。

    多重割り込みを使う場合、/Bをつけた割り込み関数から、多重割り込みで/Bをつけた割り込み関数が呼ばれると
    多重割り込みから戻った時に元の割り込みでのレジスタが壊れたままなので
    /Bを使うのは1つの割り込み関数だけにすれば大丈夫です。って/Bと/Eは両方同時に設定できないからいいのかな??
  • 現状は、多重割り込みをしないということで、割り込み関数には/Eは使用していません。受信割込み処理のみに、/Bを使用して高速化して、オーバーランエラーはでていません。