##概要
- 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割込みの後処理に問題があるのかと疑ったのですが、公式のサンプルコードを見ても後処理は割込みフラグTI
やRI
を0
でリセットするだけで良さそうです。
##割り込み処理
割込み処理は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)