中国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
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复

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


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



论坛跳转: