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よりも高レベルに設定しても改善しませんでした。

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

Parents
  • もんたさん、こんにちは。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の送信割り込みのタイミング重ならなかっただけ、ということはないでしょうか?

  • 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バイトの固定データでした。
    訂正します。
  • 送信割り込みが連発しているため、タイマ割り込みが
    途中で割り込めない状態が発生しているように見えます。

    送信割り込み処理中とタイマ割り込み処理中にどこかの
    ポートを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文字送信して即リターンさせ、そして、指定文字数送信したら送信割り込みをディセーブルにする、という作りにしますが。
  • 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;
    }
    

    タイミングを重視するならば、割り込みの禁止/許可をしないで済む方法を考えるべきでは?

    これでオーバーフロー割り込みを使って割り込み処理の中で TCNT カウンタの初期化を行ってたんであれば、そりゃ割り込み周期はどん〃ずれてきますよ。

  • > 多重割り込みも使う必要もなさそうですのでもうこのソースでもう少し動きを確認してみます。

    ハードウェアマニュアルを確認して動作の仕組みを確認されるべきと思います。
Reply Children
No Data