关于处理中断的问题。实在找不出错在哪里!

typedef struct mypcic{
pthread_mutex_t mutex;
int chid;
int coid;
int int_line;
int iid;
int tid;
}mypcic_t;
int main()
{ ULONG testdata=0x13579246;
ULONG datareceived;
mypcic_t pcip;
int iRet = ThreadCtl(_NTO_TCTL_IO, 0);
if(iRet == -1)
{
printf("Failed to gain IO privilege
");
}

memset(&pcip,0,sizeof(pcip));

pcip.int_line=5;
h429=open("/dev/c429",O_RDWR | O_NONBLOCK);
printf("h429 is %x
",h429);
WritePortLong(0x04,0x00,h429);
WritePortLong(0,0,h429); //////clear fifo
WritePortLong(0x1c,0x20,h429);
WritePortLong(0x28,0x00,h429); //cw1 //////set channel 1 cmdW
WritePortLong(0x2c,0x00,h429); //cw2 //////set channel 2 cmdw
while( !(ReadPortLong(0x08,h429)&0x10));
while( !(ReadPortLong(0x08,h429)&0x20)); //////read status reg ,see if channel1/2 cmdw over
WritePortLong(0x30,0,h429);
WritePortLong(0x10,50,h429); //////set channel 1 clock divider
WritePortLong(0x14,50,h429);
WritePortLong(0x18,0x01,h429);
//////set channel 2 clock divider
intmask = ReadPortLong(0x04,h429);

printf("the intmask is %x
",intmask);
intmask =intmask |0x04;


printf("the intmask is %x
",intmask);
WritePortLong(0x04,intmask,h429);
register_interrupt(&pcip);
ch1sendsingledata(testdata,h429);

//datareceived=readsingledata(h429);
// printf(“main data received is %x”,datareceived);



return 1;}

void *mythread(void data)
{
struct _pulse pulse;
iov_t iov;
int rcvid;
mypcic_t * mypcip;
printf("mythread
");
mypcip=(mypcic_t
)data;
SETIOV( &iov, &pulse, sizeof( pulse ) );
while( 1 )
{
printf("wait…
");

if( ( rcvid = MsgReceivev( mypcip->chid, &iov, 1, NULL ) ) == -1 ) {
if( errno == ESRCH ){
printf(“ESRCH”);
pthread_exit( NULL );
}
continue;
}

pthread_mutex_lock(&mypcip->mutex);

switch( pulse.code )
{
case c429_INTERRUPT_EVENT:
printf("pulse.code=%d
",pulse.code);
process_interrupt( mypcip );
break;

default:
printf(“i am default”);
if( rcvid )
{
printf("default
");
MsgReplyv( rcvid, ENOTSUP, &iov, 1 );
}
break;
}
pthread_mutex_unlock(&mypcip->mutex);
}

out: printf("mythread exit
");
return NULL;
}

int
register_interrupt(mypcic_t *pcip)
{
pthread_attr_t pattr;
pthread_mutexattr_t mattr;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
struct sched_param param;
struct sigevent event;
mypcic_t * mypcip;

printf( "register_interrupt
");

mypcip = pcip;

pthread_attr_init( &pattr );
pthread_attr_setschedpolicy( &pattr, SCHED_RR );
param.sched_priority = 21;
pthread_attr_setschedparam( &pattr, &param );
pthread_attr_setinheritsched( &pattr, PTHREAD_EXPLICIT_SCHED );

if((mypcip->chid = ChannelCreate( _NTO_CHF_DISCONNECT | _NTO_CHF_UNBLOCK ) ) == -1 )
{
printf( "Failed to create channel
");
return -1;
}


if((mypcip->coid = ConnectAttach( 0, 0, mypcip->chid, 0, _NTO_SIDE_CHANNEL ) ) == -1 )
{
printf("failed to attach to channel
");
ChannelDestroy(mypcip->chid);
return -1;
}

event.sigev_notify = SIGEV_PULSE;
event.sigev_coid = mypcip->coid;
event.sigev_code = c429_INTERRUPT_EVENT;
event.sigev_priority = c429_PRIORITY;
if((mypcip->iid = InterruptAttachEvent( mypcip->int_line,
&event,
_NTO_INTR_FLAGS_TRK_MSK)) == -1 )
{
printf("failed to attach event to interrupt
");
ConnectDetach(mypcip->coid);
ChannelDestroy(mypcip->chid);
return -1;
}

// create the interface thread
if(EOK != pthread_create( &mypcip->tid,
&pattr,
(void *)mythread, mypcip ) )
{
printf( "failed to create interrupt thread
");
InterruptDetach(mypcip->iid);
ConnectDetach(mypcip->coid);
ChannelDestroy(mypcip->chid);
return -1;
}

return 0;
}


int process_interrupt(mypcic_t * mypci)
{USHORT l,h;
ULONG datareceive;
mypcic_t * mypcip;
ULONG d1,d2,d3;
ThreadCtl(_NTO_TCTL_IO, 0);
mypcip=mypci;
printf( "processing interrupt!
");
d1=in32(0xe000);
printf("data1 is %x
",d1);
d2=in32(0xe000);
printf("data2 is %x
",d2);
l=(USHORT)d1&0x0ffff;
h=(USHORT)d2&0x0ffff;
c429_data_exch_read (l,h);
datareceive=((ULONG)c429_dh_buf<<16)|(0x0000ffff&(ULONG)c429_dl_buf);
printf("the result is %x
",datareceive);
InterruptUnmask(mypcip->int_line, mypcip->iid);
WritePortLong(0x04,0,h429);
WritePortLong(0x30,0,h429);
printf( "process interrupt over!
");
return 0;

第一部分是我在主程序定义了一个注册中断的函数register_interrupt(),在这个函数里,我把一个事件event与中断号绑定在一起了,然后创建了一个线程mythread来接受当中断发生时,系统自动分发的事件,来看看是否我想要的脉冲c429_interrupt_event,如果是进入process_interrupt().,在这个函数里面,我要求收到,主函数里面ch1senddata(testdata,h429)的testdata。
有以下几个问题,WritePortLong(0x18,0x01,h429); 表示我的板子的通道1发送完数据以后会产生中断,但是ch1sendsingledata(testdata,h429)也就是通道1发送数据,它发完后,的确产生了中断也进入了process_interrupt(),但是为什么中断了两次,也就是说process_interrupt()中的printf( "processing interrupt! "); 执行了两次,我在控制台,看见了两次processing interrupt! ,这不对呀,应该一次才是。难道没清中断?writeportlong(0x04,0,h429)是将中断屏蔽寄存器置0,也就是说不管什么行为,都不产生中断了,writeportlong(0x30,0,h429)就是清中断。不过我的中断号是5,我在pci -v里面看到有一个USB设备也是5。
还有一个问题,如上面的程序,我的process_interrupt()里的printf("the result is %x ",datareceive); 输出的应该是我发送到板子里FIFO寄存器的数据,也就是main()里面的testdata,但是为什么收到的是0,而不是我放进FIFO的数据。
另外,如果我把register_interrupt()与ch1senddata(),两个函数位置换换,也就是说register_interrupt()在后,收到的数据就是对的,但是中断还是产生了两次,第一次中断是我希望看到的,结果也是正确的,第二次,就是还读FIFO,但是,不该读的。小弟挖空心思还是没找出错在哪里?0xe000是我的io基地址,也就是说writeportlong(0x30,0,h429)就是往iobase+30处写0。

很想找个达人时时解疑,省得我老走弯路,我的QQ10819754,小弟愿拜师学艺。

代码很烦,念在小弟一片诚心,望 各位大哥原谅。

中断应在InterruptUnmask之前清除.

WritePortLong(0x04,0,h429);
WritePortLong(0x30,0,h429);
InterruptUnmask(mypcip->int_line, mypcip->iid);

d1,d2也是从FIFO里读出来的? c429_data_exch_read是个什么东东?

0xe000是我的io端口值,我要读出的数据就得从这里不断的读,c429_data_exch_read是读之前数据要转换一下,板子就这样做的,呵呵,不重要。
好,我试试,谢谢你

d1,d2是

我试了一下,的确是这个问题,但是为什么要这样呢,那两句放在后面不对呢?现在主要的问题就是我觉得register_interrupt放在ch1sendsingledata的前面应该是对的,但是为什么这样子反而不对呢,放在ch1sendsingledata的后面反而结果是对的,我觉得理应register_interrupt在前,ch1sendsingledata在后。望高手不吝赐教。

若InterruptUnmask在前,清中断在后,因为InterruptUnmask时中断源还
没有被清除,中断会立即在InterruptUnmask之后产生.所以要先清中断.
register_interrupt放在ch1sendsingledata的前面应该是对的,我估计在接
收中断之外你还允许了其他中断,所以在你接受到数据之前会得到中断,但不是
接受中断,而你的中断处理程序并没有判断是否是接受中断.

郁闷中

如果你有别的设备共享这个中断,那么在process_interrupt()里就不能直接去读端口,而是应该去查设备的寄存器(通常都会有一个中断状态寄存器),看看是不是你的h429造成的中断。然后再去读端口。

int process_interrupt()
{
       int intstatus;

       intstatus = read_intr_status(h429);
       if (intstatus & H429_INBOUND_DATA_INTR) {
           /* read data out of H429 */
           /* clear H429 interrupt */
       }
       InterruptUnmask()
       return 0;
}

thank you,xtang.按照你的方法,问题已经解决了。谢谢