2009-03-24 15 views
0

私は基本的に全く同じ のことをするが、それぞれ異なるデバイスからの割り込みを処理する2つの割り込みサービスルーチン(ISR)を持っています(同じタイプのデバイスですが)。したがって、ロジックは同じですが、異なるCPUレジスタとメモリ位置にアクセスします。類似のISR間でコードの重複を回避するにはどうすればよいですか?

簡単な例として、次のコードを考えてみます。私は(つまり私は、ISRのにパラメータを渡すことはできませんし、関数呼び出しを避けるべきISRの に適用される制限付きコードの重複を避けることができますどのように

extern volatile unsigned int dev1_rx_buffer; 
extern volatile unsigned int dev2_rx_buffer; 

volatile unsigned char data; 

void __attribute__((__interrupt__)) _dev1_interrupt(void) 
{ 
    /* Clear interrupt flag */ 
    dev1.IF = 0; 

    if (dev1.IS_FULL) { 
     /* Read data from device */ 
     data = dev1_rx_buffer; 
    } else { 
     /* do something else using registers of device 1 */ 
    } 
    /* More stuff using registers of device 1 */ 
} 

void __attribute__((__interrupt__)) _dev2_interrupt(void) 
{ 
    /* Clear interrupt flag */ 
    dev2.IF = 0; 

    if (dev2.IS_FULL) { 
     /* Read data from device */ 
     data = dev2_rx_buffer; 
    } else { 
     /* do something else using registers of device 2 */ 
    } 
    /* More stuff using registers of device 2 */ 
} 

をオーバーヘッドのために )。

私は2つのISRを生成するためのテンプレートを、より高いレベルのスクリプト言語を使用して作成することを考えましたが、CまたはCのプリプロセッサマクロのみを使用するソリューションを希望します。

答えて

2

なぜデバイスとバッファへのポインタを取得するインラインヘルパー関数を使用しないのですか?

私は生成されたアセンブリをチェックして、コンパイラが期待したとおりに動作することを確認します。

マクロを使用することもできますが、IMHOこれは長い間この機能には適していません。

2

同じタイプのデバイスを処理している場合、複数の割り込みを処理する割り込みハンドラを1つだけ持つことはかなり妥当です。あなたはどの旗が一番上に設定されているかを確認し、そこから続けることができます。しかし、2つの割り込みハンドラが異なるタイプのデバイス用で、同じロジックフローを持っている場合は、これをお勧めしません。

6

このような場合は、通常、ISR(ベクトルエントリポイント)のフロントエンドにデバイス固有のブロックへのポインタを設定してから、そのブロックへのポインタで共通コードを呼び出します。

大まか

void __attribute__((__interrupt__)) Isr1(void) 
{ 
    CommonISR(&dev1info); 
} 

void __attribute__((__interrupt__)) Isr2(void) 
{ 
    CommonISR(&dev2info); 
} 

void CommonISR(Foo *devptr) 
{ 
    devptr->count = 0; 
    devptr->reset(); 
    etc... 
} 

dev1infoとdev2infoが起動時に初期化/設定されている(ISR構文等を気にしません)。彼らはHWレジスタなどへのポインタを持っているかもしれません...

+0

コンパイラでは、関数呼び出しを避けるために、CommonISRを明示的にインラインで宣言する必要があります。さもなければこれはおそらく私がやることです。ありがとう。 – davitenio

1

あなたのコンパイラは関数呼び出しを最適化しないでしょうか?
あなたは間違いなく、自動的にこのコードを生成するためのマクロを使用することができますが、それは少し醜いようになります。

#define __CONCAT(a,b) a ## b 

#define ISR_DECLARE(name) \ 
\ 
void __attribute__((__interrupt__)) _CONCAT(name,_interrupt)(void) \ 
{ \   
    /* Clear interrupt flag */ \ 
    name.IF = 0; \ 
    \ 
    if (name.IS_FULL) \ 
    { \ 
     /* Read data from device */ \ 
     data = _CONCAT(name, _rx_buffer); \ 
    } \ 
    else \ 
    { \ 
     /* do something else using registers of device 1 */ \ 
    }\ 
    /* More stuff using registers of device 1 */ \ 

}

、その後:

ISR_DECLARE(dev_1) 

ISR_DECLARE(dev_2) 

しかし、私は強くすることをお勧め前の記事で示唆されているように、コンパイラがインラインでコードを最適化するかどうか最初に確認してください。

+0

明らかに、関数をインラインで明示的に宣言し、コンパイラが関数呼び出しを最適化するようにコンパイラに "-finline"フラグを追加する必要があります。ありがとう – davitenio

+0

私はこれが好ましいオプションですが、あなたが明示的にマクロを望んでいたので私は例を与えました。 – Ilya

関連する問題