RX210でタイマオーバーフロー割り込み周期がずれる

お世話になってます。

RX210で、8bitのtmr0を5ms周期、tmr1を500us周期でオーバーフロー割り込み
として使っているのですが、SCIの送信割り込みを使ってデータ送信
を行うようにするとtmrの周期がずれてしまいます。
SCIの送信割り込みは500msに1回5バイト程度のデータをテスト的に
送信しています。
送信タイミングに同期して周期が遅れているようで、SCIの送信を止めるときっちり

5ms、500us周期で割り込みがかかります。

割り込みはレベルはtmr0、1、SCIともにOVIに4を設定しています。
tmr0、1を5などSCIよりも高レベルに設定しても改善しませんでした。

他に見るべきところは有りますでしょうか?

  • わわいです
    まあ、私の私見ですが、
    多重割り込みを使わなくても動くように作るもの、です。
    そもそも割り込み処理に、他の動作に影響するだけの時間がかかるというのは何か間違ってますね
    そりゃVsync割り込み中にビデオメモリをブロック転送せにゃならん、とかどーしても時間をかけざるをえない場合はありますが、そこは特別に多重を許可する、というアプローチですね
  • >SCIの送信割り込みは500msに1回5バイト程度のデータをテスト的に
    送信しています。
     
     これが原因でしょう。割り込みは瞬時に処理が終わるように考えなければなりません。
     5バイト送るまで待っていたら、時間が掛かり過ぎます。9600ボーで1バイト送るのに1msぐらい掛かります。
     5バイトだったら4msぐらい掛かります。最後のバイトを書いたら送信終了を待たず割り込み処理を終えるので、4msに成ります。

     1バイト書いたら直ぐに割り込みを終了するように改善が必要でしょう。
  • もんたさん、こんにちは。NoMaYと申します。

    少し質問があります。tmrの周期がずれるとのことですが、どういう風(例えば、最初の1バイトを送信する時に、あるいは最後の1バイトを送信する時に、とか)に、どの程度ずれるのですか?

    また、500ms毎にデータを送信するとのことですが、この500msのタイミングは何で作っていますか? もうひとつタイマを使っている? それともtmr0(もしくはtmr1)を100回(もしくは1000回)カウントしてタイミングを計っているのでしょうか?

    あと、SCIの送信割り込みを使ってデータ送信を行っているとのことですので、まず、この500msのタイミングで1バイトを送信して(というか送信バッファに書いて)、以後、送信終了(もしくは送信データエンプティ)割り込みで次の1バイトを、それによる送信割り込みで更に次の1バイトを、と順に送信しているのですよね?(リカルドさんが仰っていたことでは送信割り込みの出番が全く無くて話が合わないような気がしましたので。)

    それから、5バイト程度のデータといのは"Hello!"といったような固定データなのでしょうか? それともA/D変換など多少なりとも時間の掛かる何らかの処理をして得られるデータなのでしょうか?

    それで、返事を聞く前に推測を書いてしまうのですが、もしずれが数usから数十usというのなら、今までのH8SやR8Cでは、たまたま運良く5ms周期や500us周期の割り込みとSCIの送信割り込みのタイミング重ならなかっただけ、ということはないでしょうか?

  • リカルドさん

    SCIのドライバは今回のRX用にH8Sの物を改造して移植しました。
    もしかしたらドライバに不具合があるのかもしれませんので見てみます。
    /* 送信割り込み */
    void sendInterrupt(char ch)
    {
    const struct IORegs *r;
    struct RingBufferTx *tx_p;
    unsigned char ssr;

    r = &reg[ch]; /* アクセス用ポインタ設定 */
    tx_p = &tx[ch];

    if(tx_p->count != 0){ /* 送信データがある */
    OUTPORTB(r->tdr, tx_p->buffer[tx_p->load++]); /* 送信 */

    ssr = INPORTB(r->ssr);
    while(!TESTBIT(ssr, 0x04)){ /* TEND 送信完了待ち */
    ssr = INPORTB(r->ssr);
    }

    if(tx_p->load >= COM_TX_BUF_SIZE) /* リングバッファ構築 */
    tx_p->load = 0;
    getCountTx(tx_p);

    if(tx_p->count == 0){ /* データ送信完了 */
    /* 送信割り込み禁止 */
    intTxEnable(ch, 0);
    }
    }
    }
  • NoMaYさん

     

    送信の500msの周期はTMR0の5msの周期を利用して500ms間隔で送信しています。

    500ms周期でバッファに5バイトライトしています。

    以下の処理が5バイト分(5回)コールされます。

    送信データはaaaa\r\nという固定文字です。

    int rsPutch(char ch, const char c)

    {

    struct RingBufferTx *tx_p;

    tx_p = &tx[ch]; /* アクセス用ポインタ設定 */

    if(tx_p->count == COM_TX_BUF_SIZE){ /* バッファフルの時はエラーで戻る */

    return -1;

    }

    clrpsw_i(); /* 割込禁止 */

    tx_p->buffer[tx_p->save++] = c; /* 1バイトデータのバッファ読み込み */

    if(tx_p->save >= COM_TX_BUF_SIZE) /* リングバッファ最大 */

    tx_p->save = 0; /* 最初に戻す */

    getCountTx(tx_p); /* バッファデータ算出 */

    intTxEnable(ch, 1); /* 送信割り込み許可 */

    setpsw_i(); /* 割込許可 */

    return 0;

    }

     

    以下はtmr0の5ms周期の波形ですが

    ずれは結構大きくて遅れるときは10msとかになっている感じです。

  • 送信しているデータは
    5バイトではなく
    正しく18バイトの固定データでした。
    訂正します。
  • >SCIのドライバは今回のRX用にH8Sの物を改造して移植しました。
    もしかしたらドライバに不具合があるのかもしれませんので見てみます。
     
     これは要注意ですね。H8/3052からRX621に移植しても動かなかった。
     このフォーラムの何処かに、それについて語ってあります。

     H8/3052もRX621もレジスタ名は同じだし、同じような説明が書いてあります。
     しかしハードの内容が違う。

     要点はSCIの設定は割り込みを使うように書く。ポーリングであっても。
     これだけでは割り込みは掛からず、割り込みの許可/不許可、優先順位などを設定するレジスタが有ります。
     ポーリングしたいときは、このレジスタの割り込みの許可/不許可を操作する。
  • 送信割り込みが連発しているため、タイマ割り込みが
    途中で割り込めない状態が発生しているように見えます。

    送信割り込み処理中とタイマ割り込み処理中にどこかの
    ポートをHにしてモニタしてみると、全体像が見えると思います。

    送信割り込みの内容ですが、TDRに書き込んで送信してから
    TENDを待つ構造になっているのは、待ち時間が長くてもったいないです。

    送信データエンプティ割り込み(TXI)を使っているなら、
    その時点でTDRは空いているため、TDRに書き込むだけで良く
    送信割り込み間の空き時間を長くする事ができ、
    タイマが割り込みやすくなるはずです。

    H8SよりRXの方が処理速度が速くなったため、タイマ割り込みが
    割り込みにくくなってしまったのが原因ではないかと思っているの
    ですが、同一優先度の場合、ベクタ番号が小さい方が優先度が高いはずで、
    CMT,TMRの方がSCIよりも優先度が高く、なぜタイマが割り込めないのかが
    疑問として残っています。

  • Higetaka さん

    sendInterruptはTXI割り込みで利用しています。
    試しに送信完了待ちを外してみたところ、なんと正常に動くようになりました。
    // ssr = INPORTB(r->ssr);
    // while(!TESTBIT(ssr, 0x04)){ /* TEND 送信完了待ち */
    // ssr = INPORTB(r->ssr);
    // }

    H8Sのソースを改めて確認してみましたが、そちらも送信完了待ちはしておりませんでした。
    移植している途中色々あって送信完了待ちを入れてしまっていたようです。
    多重割り込みも使う必要もなさそうですのでもうこのソースでもう少し動きを確認してみます。
    アドバイスありがとうございます。
  • わわいです
    その送信完了ウェイトを抜いて、送信動作は正常ですか?
    考えなしにそのウェイトを抜いたらおかしくなるような気がしますが。

    ということはよこにおいといて、割り込みルーチン内でウェイトさせるというのは作り方が悪いです
    そこらへんどーにかしましょう。
    一般的には、送信割り込みでは1文字送信して即リターンさせ、そして、指定文字数送信したら送信割り込みをディセーブルにする、という作りにしますが。