2017-02-08 1 views
3

を使用してでコンパイルするために、保護モードでハードウェア割り込みハンドラを設定しようとしています。可能な限り小さなコードがあります(タイマー割り込み)。保護されたハードウェア割り込みハンドラーがスタックしていますか? (DJGPP)

#include <dpmi.h> 
#include <go32.h> 
#include <stdio.h> 

unsigned int counter = 0; 

void handler(void) { 
    ++counter; 
} 
void endHandler(void) {} 

int main(void) { 
    _go32_dpmi_seginfo oldInfo, newInfo; 

    _go32_dpmi_lock_data(&counter, sizeof(counter)); 
    _go32_dpmi_lock_code(handler, endHandler - handler); 

    _go32_dpmi_get_protected_mode_interrupt_vector(8, &oldInfo); 

    newInfo.pm_offset = (int) handler; 
    newInfo.pm_selector = _go32_my_cs(); 
    _go32_dpmi_allocate_iret_wrapper(&newInfo); 

    _go32_dpmi_set_protected_mode_interrupt_vector(8, &newInfo); 

    while (counter < 3) { 
     printf("%u\n", counter); 
    } 

    _go32_dpmi_set_protected_mode_interrupt_vector(8, &oldInfo); 
    _go32_dpmi_free_iret_wrapper(&newInfo); 

    return 0; 
} 

私はハンドラをチェーンしているわけではなく、それを置き換えることに注意してください。カウンターは1を超えて増加しないので(メインループを止めることはない)、ハンドラーが正しく戻らないか、一度だけ呼び出されると推測されます。もう一方のチェーンはうまくいきます(ラッパーラインを外し、set_protected_modechain_protected_modeに置き換えてください)。 行がありませんか?

+2

'counter'は' volatile'とマークする必要があります。 –

+0

また、 '_go32_dpmi_lock_code'と' ... data'の呼び出しで不要なキャストを取り除きます。 'void *'(任意の型のポインタを受け付ける)と 'size_t'(これは' sizeof'の結果です)をとります。 –

+1

また、 'handler'のサイズを試して計算するために' endHandler'を使用することは疑わしいです。あなたが期待しているように 'endHandler'が' handler'の直後に来ることは何も保証していません。 GCCでは、より良い解決策は 'handler'をカスタムセクションに置き、リンカスクリプト変数を使ってそのサイズを取得することです。しかし私はDJGPPについてはわかりません。 –

答えて

0

古いハンドラは割り込みコントローラに割り込みのアサートを停止するように指示するので、ドキュメント内のJonathon Reinhartの例のように、古い割り込みハンドラをチェーンする必要があります。また、BIOSのクロックを刻々と変化させるという利点もありますので、プログラムを実行するたびに数秒かかることはありません。それ以外の場合は、割り込みハンドラが返すと、CPUは直ちにハンドラを再度呼び出すため、プログラムは無限ループに陥ります。

また、GCCがendHandlerhandlerの後に配置するという保証はありません。キャストは、ポインタからの自動変換をするには、関数の型にありませんように、ここで必要とされる

_go32_dpmi_lock_code((void *) handler, 4096); 

注:私は上のページhandler開始され、それがページをまたぐ場合には、次のページの両方をロックするだけで簡単にお勧めしますvoidへのポインタ。

+0

ありがとう! _that_重要な古いハンドラに関する情報は持っているといいです。私はそれをさらに調べて、[古いハンドラーがおそらく何をするのか]を知った。(http://webpages.charter.net/danrollins/techhelp/0105.HTM) 'outportb(0x20、0x20);それは古いもののように動作させるために。 しかし、あなたが言及した追加の利点が本当にあるなら、私はそれを連鎖で残します。 – tobywoby

+0

@tobywoby BIOSクロックを完全にエミュレートしないDOSBoxでは、ホストオペレーティングシステムのクロックを使用するなどの時間を失うことはありません。実際のPCでは、BIOSのタイマー割り込みハンドラが現在の時刻を記録するためにBIOSで使用されるカウンタをインクリメントするため、時間が失われます。 –

関連する問題