中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
作者:
标题: DOS中中断处理冲突难题 上一主题 | 下一主题
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 ]

2006-6-17 16:45
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
xiaoyuer06
初级用户




积分 86
发帖 35
注册 2005-10-6
状态 离线
『第 2 楼』:  

定时中断好像不能直接用0x08,而应该用0x1c

2006-6-27 18:23
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
mrfstamp
新手上路





积分 10
发帖 3
注册 2006-6-17
状态 离线
『第 3 楼』:  

这两个有什么区别吗?
但是单独用一个的时候,即只有08中断的时候是没有问题的阿,这又是为什么呢?
另外我在看资料的时候,发现有这样一个说法:“保存DOS的数据交换区(SDA)可以安全地使用的DOS的功能.SDA保存了DOS几乎所有内部数据,如果保存(5D06H)和恢复(5D0BH)SDA ,DOS就变成在任何时候都可以重入的了.“
谁可以给我解释一下吗?谢谢!!!

2006-6-29 14:38
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
mrfstamp
新手上路





积分 10
发帖 3
注册 2006-6-17
状态 离线
『第 4 楼』:  

0x1C是软中断,08是硬中断,08为操作系统所用,我在修改后

2006-6-29 16:10
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: