关于中断号的问题,请各位大侠指点

小弟最近在写一个程序,需要用中断服务程序,可是在调试之后发现无法进入中服,但是InterruptAttach()的返回值正常,所以怀疑是irq出了问题,请问如何检查中断是否挂上,再问irq与interruptatach参数中的Interrupt vector num一样么?谢谢大家!

在 x86 上一般都直接用 pci 命令就能看到中断了吧

在其他cpu类型上,就不知道了

x86的话,是一样的。

如果你有怀疑,试试挂别的中断,比如时钟中断(irq=0),看你的服务程序会不会响应。

这是我的程序,麻烦帮我看看
#include “DeviceControl.h”
int initpci();
uint32_t* MemBase
;
uint32_t PortBase_9054
;
HANDLE hMotor;
int interruput;
unsigned int irq
;
struct sigevent event; //for interrupt event

const struct sigevent *int_handler(void *area, int id)
{


WritePortLong(0x4,0x0,hMotor);//清中断
ReadPortLong(0x14, hMotor);//清中断
WritePortLong(0x4,0x2,hMotor);//开中断

return &event;
}


void *int_thread_proc(void *arg)
{
int i;
int int_id;
int port14;




printf(“irq is %d\n”,irq);
int_id=InterruptAttach(irq,&int_handler,NULL,0,0);
printf(“int_id is %x\n”,int_id);



if(-1==int_id)
{
fprintf(stderr," Interrupt failed!\n");
}

while(1)
{

InterruptWait(0,NULL);
fprintf(stderr," Interrupt receive got!\n");
port14=ReadPortLong(0x14, hMotor);
fprintf(stderr,“Interruput is %x\n”,port14);


}
//InterruptDetach(int_id);



}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
uint32_t test1,test2,test3;
BOOL test;
initpci();
event.sigev_notify=SIGEV_INTR;
ThreadCtl(_NTO_TCTL_IO,0);
hMotor=open("/dev/Motor",O_RDWR | O_NONBLOCK);
WritePortLong(0x4,0x0,hMotor);
ReadPortLong(0x14, hMotor);
test1=ReadPortLong(0x0,hMotor);
printf(“0x0 is %x\n”,test1);
EnableNtr(hMotor);
pthread_create(NULL,NULL,int_thread_proc,NULL);
sleep(2);
WritePortLong(0xec,0x0,hMotor);
sleep(5);
}

int initpci()
{
//init pci-device ,finding out resource and irq
unsigned did, vid, busnum, devfuncnum ;
int phdl;
int iRet, index;
int pidx;
int count;
void* hdl;
char* buff;
uint64_t mem;
uint64_t port;


motorpcic_t motorpcip;

unsigned int buf;
char buf_irq;

phdl=pci_attach(0);
if( phdl == -1 )
{
printf( “Unable to initialize PCI\n”);
exit(0);
}
MotorServer = phdl;

index=0;
do
{
iRet = pci_find_device(motorDeviceid,motorVendorid, index++, &busnum, &devfuncnum);
if(iRet == PCI_SUCCESS)
{
printf( “Found our device\n”);
break;
}
}while(iRet != PCI_DEVICE_NOT_FOUND);
if(iRet != PCI_SUCCESS)
{
printf(“Couldn’t find the device\n”);
/* Disconnect from the PCI server */
pci_detach( phdl );
exit(0);
}
memset(&MotorDevInfo, 0, sizeof(MotorDevInfo));//motorDevInfo
pidx = 0;
MotorDevInfo.VendorId = motorVendorid;
MotorDevInfo.DeviceId =motorDeviceid;
hdl = pci_attach_device( NULL, PCI_SEARCH_VENDEV|PCI_SHARE, pidx, &MotorDevInfo);

if (hdl == NULL)
{
printf(“unable to locate adapter\n”);
pci_detach(phdl);
MotorServer=0;
exit(0);
}
else
{
MotorDevice = hdl;
}

pci_read_config( MotorDevice,
0x3c,
1,
sizeof(buf),
&buf
);
irq=buf&0x000000ff;
printf(“irq should be:%x\n”,irq);

pci_read_config( MotorDevice,
0x14,
1,
sizeof(buf),
&buf
);

port= PCI_IO_ADDR(buf);
PortBase_9054=mmap_device_io( 0x80 , port);
printf(“9054 space: %x\n”,PortBase_9054);

pci_read_config(MotorDevice,
0x18,
1,
sizeof(buf),
&buf
);
printf(“buf space: %x\n”,buf);
mem = PCI_MEM_ADDR(buf);
// printf(“mem space: %x\n”,mem);


MemBase=(uint32_t *)mmap_device_memory(0,
0x20000,
PROT_READ|PROT_WRITE|PROT_NOCACHE,
MAP_PHYS|MAP_SHARED,
mem);
if ( MemBase == MAP_FAILED ) {
perror( “mmap_device_memory for physical address 0xb8000 failed” );
exit( EXIT_FAILURE );
}
printf(“mem space: %x\n”,MemBase);


}

BOOL EnableNtr(HANDLE handle)
{

// WritePortLong(0x68, 0x0f010900,handle);
out32((uintptr_t)(PortBase_9054)+0x68,0x0f010900)
;
return 1;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////


[/code]
程序的运行结果是进入了子线程,但不进入中断服务程序,在主线程退出后,子线程也退出!可以肯定的是硬件确实发了中断!

中断Handler可以单步跟踪么?!

自己加个全局的标置位看看有没有运行int_handler()就可以了吧。

nakeyfish,我看了您的回复,我加了,进步了handler,我用的是resource manager,是不是挂接中断线程必须在创建线程池之前呢?你那里有没有interruptattacheevent的例子,是不是要用这个挂接中断呢?

interruptattacheevent应该也是一样的。

我看了一下代码,有两个地方可以试一下:
1.ThreadCtl(_NTO_TCTL_IO,0); 放到线程代码中?!
2.增加Flag:InterruptAttach(irq, int_handler, NULL, 0, _NTO_INTR_FLAGS_TRK_MSK );

两个示例代码:

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>

char            *progname = "intsimple";
struct sigevent int_event;  // the event to wake up the thread

main (int argc, char **argv)
{
    int id;
    int count = 0;
	
    setvbuf (stdout, NULL, _IOLBF, 0);

    printf ("%s:  starting...\n", progname);

    // request I/O privity
    ThreadCtl(_NTO_TCTL_IO, 0 );
	
    // set up an event for the handler or the kernel to use to wake up
    // this thread.  Use whatever type of event and event handling you want
	
    SIGEV_INTR_INIT( &int_event );
    // either register an interrupt handler or the event
	
	id = InterruptAttachEvent(1, &int_event, _NTO_INTR_FLAGS_TRK_MSK );
	
    while (1) {
        // block here waiting for the event
		InterruptWait(0, NULL );
        // if using a high frequency interrupt, don't print every interrupt
        InterruptUnmask( 1, id );
        printf ("%s:  we got a keyboard interrupt and unblocked (%d)\n", 
                progname, count++);
    }   
}



#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>

char            *progname = "intsimple";
struct sigevent int_event;  // the event to wake up the thread

const struct sigevent *hdlr( void *blah, int id )
{
	
	static int count = 0;
	if (++count > 1500 )
	{
		count = 0;
		return &int_event;
	}
	return NULL;
}

main (int argc, char **argv)
{
    int id;
    setvbuf (stdout, NULL, _IOLBF, 0);

    printf ("%s:  starting...\n", progname);

    // request I/O privity
    ThreadCtl(_NTO_TCTL_IO, 0 );
	
    // set up an event for the handler or the kernel to use to wake up
    // this thread.  Use whatever type of event and event handling you want
	
    SIGEV_INTR_INIT( &int_event );
    // either register an interrupt handler or the event
	
    id = InterruptAttach(0, hdlr, NULL, 0, _NTO_INTR_FLAGS_TRK_MSK );
	
    while (1) {
        // block here waiting for the event
        InterruptWait(0, NULL );
        // if using a high frequency interrupt, don't print every interrupt
      
        printf ("%s:  we got an event after 1500 timer ticks and unblocked\n", progname);
    }   
}

我试了还是不不行,我得到的irq是从pci配置寄存器读出来的,它和从pci_dev_info结构体得到的irq一样么,怎样从pci_dev_info里得到irq,从谢谢大家热心的回复!

irqnum = MotorDevInfo.Irq

你能确定一定有中断进来? 看一下中断状态寄存器.

computer,Thanks!我试了,通过您说的那种方式读出的Irq是0,现在已证实我通过读配置寄存器,读出中断号没问题了,但我用这个程序还是进不了中服。
我现在改用InterruptAttachEvent可以进中服了,但为此好像都来两个中断,而我只给了一个中断,我觉得是我开关中断没设好,我不知道应该在哪个地方用InterruptUnmask和InterruptMask,请知道的大侠指点一下!

0?蹊跷.
InterruptAttachEvent可以的话,InterruptAttach也应该可以.
中断产生后内核作的第一件时就是屏蔽当前中断,所以不需要调用InterruptMask.
用InterruptAttach的话,不用InterruptUnmask,中断服务结束后内核会自动UNMASK中断.
用InterruptAttachEvent的话,需要用户自己UNMASK中断,一般在所有中断因素都被处理过之后作.

Mr computer,您说的我已经试了,还是不行,我在进入中断程序后,关了中断,也会又一次执行中断程序,请问InterruptWait的中断是任何外部硬件中断么?会不会是其他的硬件有干扰,谢谢!

InterruptWait(), InterruptWait_r()
These kernel calls wait for a hardware interrupt. The calling thread
should have attached a handler to the interrupt, by calling
InterruptAttach() or InterruptAttachEvent(). The call to InterruptWait()
or InterruptWait_r() blocks waiting for an interrupt handler to return
an event with notification type SIGEV_INTR (i.e. a hardware interrupt).

就是说你挂了哪个,就等哪个.
有硬件有干扰的话那就是硬件有问题了,一般不会有.
你用"pidin irq"看看有没有设备共享中断.