mrfstamp
新手上路
积分 10
发帖 3
注册 2006-6-17
状态 离线
|
『楼 主』:
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();
}
[ Last edited by mrfstamp on 2006-6-17 at 17:41 ]
|
|