Unable to detect Interrupts from DIO board

Hi guys,

I has an embedded device which has a PCM-3724 DIO module attach to it.
The DIO module is a board which provides 6 8-bit ports and 2 interrupt lines.

My job here is to write an ISR which is trigger by one of the interrupt lines on the board. This is also used to test the interrupt lines on the board. However my problem now is that i was not able to detect any interrupts from it.

#include
#include
#include <stdlib.h>
#include <stdio.h>
#include <hw/inout.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

using namespace std;

#define PortA0 0x00 //Port A0
#define PortB0 0x01 //Port B0
#define PortC0 0x02 //Port C0
#define PortModeReg0 0x03 //Port0 mode register
#define PortA1 0x04 //Port A0
#define PortB1 0x05 //Port B0
#define PortC1 0x06 //Port C0
#define PortModeReg1 0x07 //Port0 mode register
#define PortD0 0x08 //PortD0 Used to set the direction of the Ports
#define PortD1 0x09 //PortD1 Used to Enable/Disable the port
#define INTR_PORT0 0x0A //interrupt for port0
#define INTR_PORT1 0x0B //interrupt for port1
#define BASE_ADDR 0x300 //base addr for IO card
#define REG_LEN 0x0B //length of reg

#define IRQ 3

struct sigevent event;
void* int_thread (void *arg);
const struct sigevent * isr_handler (void *arg, int id);
int intId;
uintptr_t addr;

int main ()
{
// enable I/O privilege
if(ThreadCtl(_NTO_TCTL_IO, 0) == -1)
{
//printf(“thread ctl error\n”);
fprintf(stderr, “%s”, strerror(errno));
exit(-1);
}

// perform initializations, etc. 
event.sigev_notify = SIGEV_INTR; 



//initialization ON THE BOARD
if((addr = mmap_device_io(REG_LEN, BASE_ADDR)) == MAP_DEVICE_FAILED)
{
	//printf("thread ctl error\n");
	fprintf(stderr, "%s", strerror(errno));
	exit(-1);
}

out8(addr + PortD1, 0x00);			/*Disable all gates*/
out8(addr + PortModeReg0, 0x80); 	/*Set A0, B0 and C0 to output mode*/
out8(addr + PortD0, 0xFF);			/*set all port direction to output*/
out8(addr + PortD1, 0xFF);			/*Enable all gates*/

// attach the ISR to IRQ
//intId=InterruptAttach (IRQ, &isr_handler, NULL, 0, 0); 
intId=InterruptAttach (_NTO_INTR_CLASS_EXTERNAL| IRQ, &isr_handler, NULL, 0, _NTO_INTR_FLAGS_END);
cout <<"intId = "<< intId<<endl; 
//unmask IRQ
//cout <<"IntUnMask = "<< InterruptUnmask (IRQ , intId)<<endl;
cout <<"IntUnMask = "<< InterruptUnmask (_NTO_INTR_CLASS_EXTERNAL| IRQ , intId)<<endl;

//create a thread to wait for interrupt
pthread_create (NULL, NULL, int_thread, NULL);
//InterruptEnable();
cout <<"Press any key to generate a interrupt"<<endl;
getchar();

/* PC04 = 0-> Enable Interrupt*/
 
 out8(addr + PortC0, 0x01);
 printf("Port C0 = %x\n",in8(addr + PortC0));
 sleep(1);
 out8(addr + PortC0, 0x00);
 printf("Port C0 = %x\n",in8(addr + PortC0));
 sleep(1);
 out8(addr + PortC0, 0x01);
 printf("Port C0 = %x\n",in8(addr + PortC0));
 //cout <<"Port C0 = "<<in8(addr + PortC0)<<endl;
sleep(20);

 cout <<"Press any key to quit"<<endl;
 getchar();	 
 /*Set Ports to input to release IRQ*/
 out8(addr + PortC0, 0x9B);
 out8(addr + PortD1, 0x00);
 out8(addr + PortD0, 0x00);
 out8(addr + PortD1, 0xFF);

}

void* int_thread (void *arg) {
cout << “Enter Thread” << endl;
if(InterruptWait (0, NULL) == -1)
cout <<“Error in Interrupt Wait”<<endl;
cout << “received interrupt” << endl;
}
// this is the ISR
const struct sigevent * isr_handler (void *arg, int id)
{
cout<<“I am in ISR”<<endl;
return (&event);
}

In my program, i will produce a pulse on my I/O port to trigger the interrupt. However my program will just end without calling the ISR. I has also try physically to trigger the interrupt but also it produces the same result.

I just started learning QNX like 2 to 3 weeks ago so now i really clueless where i go wrong. Hope someone here can englightened me. :slight_smile:

Anyway thanks for reading.

I beleive the thread that does the InterruptWait must be the same that does the InterruptAttach.

That being said, if you had an interrupt your machine would most probably have crashed, because you cannot use function like cout in an ISR. Use InterruptAttachEvent instead to get rid of the isr_handler all together.

IRQ 3 is odd because that is where the 2nd serial port usually live.

Thanks for the reply, finally i know why it crashes when i see the sentence “I am in ISR”…haha

I also has my doubts about the IRQ level…According to the DIO module shown in my picture, it actually let me select the IRQ level from IRQ2 to IRQ7 for each interrupt line. Therefore i just choose the highest IRQ level which is 3 since IRQ 2 can’t attach to any ISRs.

For my case, which IRQ level is the most suited for me if IRQ 3 is inappropriate?

3 could be ok if you disable the serial port. It’s hard to say which you can use it all depends on the hardware

Yahoo…finally i can detect interrupts from DIO module but strangely, only from IRQ 6…i thought IRQ can be shared by multiple devices?..Oh yeah…thanks for ur advices mario…not for u.i will still be scratching my head looking blankly at the device…haha…

Thanks for sharing your excitement with us ;-)

I assume your card is ISA, with ISA you cannot share interrupt, it’s an electrical thing ;-) The ISA bus wasn’t design for that.