0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

CH559での、UART0割込みとUSB割込み併用時の問題

Last updated at Posted at 2021-12-29

##概要

  • CH559でUART0割みとUSB割り込みを併用すると、ほぼUSB割り込みが発生しなくなる
  • 対処法はふたつある
    • ダミーのバイトをUART0で送信し、USB割込みが発生するタイミングを与える
    • bIP_USBを1にして、USB割り込みの優先度を上げる

##はじめに
CH559LをDeviceモードで使用し開発を行っています。UART0はハードウエアのバッファがないので、1バイト受信する度に割り込み処理でデータを刈り取ってやらないと簡単にデータを取りこぼします。そう思いUART0の割り込み処理を追加したところUSB割込みが発生しなくなりました。

##開発環境

  • Windows 10
  • wsl
  • SDCC

##問題の詳細
USB割込みが発生しなくなったので原因を調べたところ、UART0割込みを許可(ES=1)するとUSB割込みが発生しなくなることがわかりました。
USBよりもUART0の方が割込み優先度が高いのでUART0割込みの後処理に問題があるのかと疑ったのですが、公式のサンプルコードを見ても後処理は割込みフラグTIRI0でリセットするだけで良さそうです。

##割り込み処理
割込み処理はsdccの書式に従って下記のように記述しました。

void UART0(void) __interrupt INT_NO_UART0 __using 1
{
    ES = 0;                // UART0割込みを一時禁止
    if(RI)
    {
        enqueue(SBUF);     // 受領したバイトを自前のFIFOバッファにキューイングする
        RI = 0;            // Receive割り込みをクリア
    }
    if(TI)
    {
        TI = 0;            // Transmit割り込みをクリア
    }
    ES = 1;                // UART0割込みを再許可
}

void DeviceInterrupt( void ) __interrupt INT_NO_USB __using 1
{
    ...                    // 公式のサンプルコードを流用
}

void main(void)
{
    ...
    IE_USB = 1;            // USB割り込み許可
    ES = 1;                // UART0割り込み許可
    EA = 1;                // 割込み許可
    while(True)
    {
        ...
    }
}

##問題の調査と対策

ところがさらにデバッグしていると、稀にUSB割込みが発生することがあります。どうやらUART0割込みを終了させた直後にUSB割込みが発生する余地があるようです。何故このタイミングだけUSB割込みが発生するのかは不明ですがErattaの匂いがします。

###対処法1 ダミーデータをUART0で送る
メインループ中にて、何でもいいからデータを送ると、TI=1のUART0割込みが終わった後に、USB割込みが発生します(必要がない時は、USB割込みは発生しません)。

void main(void)
{
    ...
    while(True)
    {
       ...
       if(timerinterval > 10)  // Timer0で 1ms毎にカウントされる自前のタイマー。コードは省略。
       {
           timerinterval = 0;
           SBUF = 0xFF;        // 10ms毎になんでもいいからデータを送ると、送信後TI=1のUART0割込みが発生し、割り込み終了後にUSB割込みが発生する
       }
    }
}

###対処法2
こちらの方が本命かもしれません。

CH559LはIP_EXに値を設定することで、拡張割込みの優先度を変更(*)することが出来ます。USB割込みを優先させることで、USB割込みが正しく発生するようになります。
この場合、当然ですがUSB割込み発生中はUART0割込みが発生しないので、USB割込みを速やかに終了させUART0のデータを取りこぼさないよう注意が必要です。

(* CH559の機能じゃなくてMCS51の機能かもしれません)

void main(void)
{
    ...
    IP_EX |= bIP_USB;      // USB割込みを優先に指定する
    IE_USB = 1;            // USB割り込み許可
    ES = 1;                // UART0割り込み許可
    EA = 1;                // 割込み許可
    while(True)
    {
       ...
    }
}

##さいごに
はじめてQiitaに記事を投稿してみました。おかしな箇所があったら、ぜひTwitter@lalalaroot196までご連絡ください。

##参照
格安USBホストマイコンCH559をいじってみた(大盛)

[CH559日本語資料]
(https://lang-ship.com/reference/unofficial/CH559_Doc_Japanese/docs/16-usb/)

[https://github.com/atc1441/CH559sdccUSBHost]
(https://github.com/atc1441/CH559sdccUSBHost)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?