AVR
V-USB

V-USBでタイミングクリティカルな処理を行う。

V-USBを使ってタイミングクリティカルな処理を行う方法。

V-USBを使用するにあたってインタラプト転送で使用する場合約10msごとにUSBの割り込みが発生し他のデバイスなどと通信中に割り込みが発生すると問題が起きるので、処理を割り込みに同期させて問題を回避しました。

例えばAppleの旧規格のキーボード(ADB)のUSBコンバーターなどを作ろうとすると、キーボードにコマンドを送信してデータの受信までにUSBの割り込みが発生した場合データを取りこぼしてしまいます。
これを避けるためUSBの割り込み発生時にフラグを立て、次の割り込みが発生する前に処理を終了させることで問題を回避させてみました。

V-USBはかなりタイミング的にシビアなコードなのでフラグを立てるコードで問題が起きないようにvusb/usbdrv内のusbdrvasmXXX.inc(クロック依存のインクルードファイル)内でUSB_INT_VECTOR:のすぐ後で最初のタイミング合わせている辺りが良いでしょう。

usbdrvasmXXX.inc
waitForJ:
    inc     YL
    sbis    USBIN, USBMINUS
    brne    waitForJ        ; just make sure we have ANY timeout
waitForK:
;The following code results in a sampling window of 1/4 bit which meets the spec.

     ldi x4,1        <ここでフラグを立てる
     sts adbSend,x4

    sbis    USBIN, USBMINUS
    rjmp    foundK
    sbis    USBIN, USBMINUS
    rjmp    foundK
    sbis    USBIN, USBMINUS
    rjmp    foundK
    sbis    USBIN, USBMINUS
    rjmp    foundK
    sbis    USBIN, USBMINUS ;[0]
    rjmp    foundK          ;[1]

usbdrvasmXXX.incはusbdrvasm.Sでインクルードされるのでフラグの変数をexternしておきます。

usbdrvasm.S
    extern  usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
    extern  usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
    extern  usbTxBuf, usbTxStatus1, usbTxStatus3
    extern  adbSend  <これ

main.cでフラグの宣言しておきます、volatile宣言を忘れずに。

main.c
volatile uchar adbSend = 0;

main内でフラグが立ったら割り込みから復帰直後と判断しフラグをクリアして処理を行います、次の割り込みまでの8msぐらいの処理ならこの様にして同期すれば問題は起きません。

main.c
      usbPoll();
      if (usbConfiguration && usbInterruptIsReady()) {

        if(adbSend == 1){

          adbSend = 0;   /*フラグをクリア*/
             メインの処理

Atmega328を使ったADBtoUSBコンバーター
SANY0056.JPG