小弟最近在写一个程序,需要用中断服务程序,可是在调试之后发现无法进入中服,但是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"看看有没有设备共享中断.