当前位置: 代码迷 >> C语言 >> DOS中中断处理冲突难题
  详细解决方案

DOS中中断处理冲突难题

热度:246   发布时间:2006-06-17 16:07:54.0
DOS中中断处理冲突难题

程序中包含两个中断,一个是定时中断,一个是串口中断,当我分别打开一个中断时,程序运行没有问题,如果同时打开两个中断,就会死机,那位高手可以指定以下,我应该注意些什么,或者我的处理哪里出了问题,谢了先!!!!

定时中断处理
void __far __interrupt new_int08(_CPPARGS)
{
/*以下是时间计数校准*/
if((++BA_Count%AsInB)!=0) ++stamp_timer_inc;
else if((++CB_Count%BsInC)==0)
if((++DC_Count%CsInD)!=0) ++stamp_timer_inc;
stamp_timer_inc=stamp_timer_inc%2;

if(stamp_timer_inc==0) stamp_timer++;

//以下判断是否需要调用系统始终处理 1/18.3s处理一次
if (--flag==0)
{
flag=11;
(*old_int08)();//dos系统时钟中断处理
}
else
{
//写入8259处理结束,以便可以触发下一次中断
asm{
//这里是否需要处理8259主片的结束,但是我没有处理的情况下中断
//也可以正常的响应。
// mov al,0x20
// out 0xA0,al
mov al,0x20
out 0x20,al
}
}
}


void setup_new_int08(void)
{
//修改8253计数值
asm{
cli
mov al,0x34
out 0x43,al
mov ax,0x1745
out 0x40,al
mov al,ah
out 0x40,al
sti
}
接管系统中断
old_int08=_dos_getvect(0x08);
_disable();//pcm5330
_dos_setvect(0x08,new_int08);
_enable();//pcm5330
}


void restore_int08(void)
{
//恢复时钟计数
asm{
cli
mov al,0x34
out 0x43,al
mov ax,0xffff
out 0x40,al
mov al,ah
out 0x40,al
sti
}
//恢复系统时钟处理
_disable();
_dos_setvect(0x08,old_int08);
_enable();
}



串口中断:
接管中断的处理语句:
serial->new_com_vect为指向interrupt_manage(__CPPARGS)的函数指针,已初始化。
{
serial->old_com_vect = _dos_getvect(ComIntn[serial->com]);
_dos_setvect(ComIntn[serial->com],serial->new_com_vect);
}

void __far __interrupt interrupt_manage(__CPPARGS)
{
_disable();

while((temp = (inportb(serial.portbase + IIR)) & IIR_MASK) != 1)
{

switch(temp)
{
case IIR_MS_ID: // modem status changed
serial.modem_status_reg
= inportb(serial.portbase+MSR); // read in useless char
break;

case IIR_TX_ID: // Request To Send char
serial.tx_running = 0;
c = queue_remove_item(&(serial.tx_queue));

if(c > -1){
serial.tx_running = 1;
serial.serial_tx_count++;
outportb(serial.portbase + THR, c&0xff);
}

break;
case IIR_RX_ID: // character ready to be read in
for( ; ; ){//如果有fifo,则将fifo中的数据完全读出才退出中断

c = (unsigned char) inportb(serial.portbase + RBR);
if(!queue_add_item(&(serial.rx_queue),c))
serial.rs232_error = 1;
serial.serial_rx_count++;
if( !serial.fifo ) break;
serial.line_status_reg = inp( serial.portbase + LSR );
//通过LSR上的状态标示来获知是否还有数据需要读取
if( !(serial.line_status_reg & LSR_DATA_READY) ) break;
}
break;
case IIR_LN_ID: // line status has changed
serial.line_status_reg
= inportb(serial.portbase+LSR); // read in useless char

break;
case 0x0c:
//超限错误处理
//
break;
default:
break;
}
}
_enable();
//恢复8259为可中断状态
outportb( PIC8259B_ICR, PIC8259_EOI );
//这里主片的控制字写不写对中断的处理影响都不很大,这是为什么呢?
outportb(PIC8259A_ICR, PIC8259_EOI);
}

void comm_on(Serial *serial)
{
int temp, pnum;

_disable();

outportb(serial->portbase + FCR , 0x0d);
temp = inportb(serial->portbase + IIR);
//判断FIFO是否有效
if(!(temp&0xc0)){
outportb(serial->portbase+FCR,0);
serial->fifo = 0;
}
else serial->fifo = 1;

temp = 0x0f;
outportb(serial->portbase + MCR, temp);

temp = IER_RX_INT|IER_TX_INT|IER_MS_INT|IER_LN_INT;
outportb(serial->portbase + IER, temp);

temp = inportb(PIC8259A_IMR) & ComIrqn[serial->com];
outportb(PIC8259A_IMR, temp);
//我不能确定这里是否合理,因为在上面的处理中,我已经成功打开了串口中断,
// temp = inportb(0x21) & 0xFB;//打开主片IRQ2
// outportb(0x21, temp);
// temp = inportb(0xA1) & 0xF7;//打开从片IRQ11
// outportb(0xA1, temp);

serial->modem_status_reg = inportb(serial->portbase + MSR);
/*modem的状态纪录*/
serial->line_status_reg = inportb(serial->portbase + LSR);
/*传输线的状态纪录*/
_enable();
}

/*下面的处理,是关闭串口*/

void comm_off(Serial *serial)
{
int temp;

_disable();
temp = inportb(serial->portbase + IIR);
if(!(temp&0xc0)) outportb(serial->portbase+FCR,0);
temp = inportb(PIC8259A_IMR) | ~ComIrqn[serial->com];
outportb(PIC8259A_IMR, temp);
outportb(serial->portbase + IER, 0);
outportb(serial->portbase + MCR, 0);
_enable();
}

[此贴子已经被作者于2006-6-17 17:32:23编辑过]

搜索更多相关的解决方案: DOS  难题  

----------------解决方案--------------------------------------------------------
友情提醒:
DOS系统是“不可重(复进)入”的。
建议作者查阅早年有关DOS的书刊。
偶已经过了DOS狂热期。
您的代码又长,所以没有看。

----------------解决方案--------------------------------------------------------
两点建议:
1。用插入汇编改写两处 _dos_setvect()
避免DOS调用“重入”。
2。求教电脑硬件坛。
----------------解决方案--------------------------------------------------------

不可重入这一点我是知道的,可能我没有说清楚,死机并不是在程序一启动的时候,而是在程序运行期间,在打开传输数据进行传输数据的期间(定时中断打开的情况下)。


----------------解决方案--------------------------------------------------------
_disable();
temp = inportb(serial->portbase + IIR);
if(!(temp&0xc0)) outportb(serial->portbase+FCR,0);
temp = inportb(PIC8259A_IMR) | ~ComIrqn[serial->com];
outportb(PIC8259A_IMR, temp);
outportb(serial->portbase + IER, 0);
outportb(serial->portbase + MCR, 0);

_enable();
关中断持续时间是否太长了?
----------------解决方案--------------------------------------------------------
  相关解决方案