InterruptAttachEvent() not working on IRQ 10

I am using QNX Neutrino 6.1.0 on an Intel XScale PXA210 (Sabinal)
applications processor.

I am attempting to use the InterruptAttachEvent() function to field
interrupts coming from a CAN controller on GPIO pin 53 of the XScale
processor. When the interrupt pin transitions from high to low, a bit
should be set in the GPIO edge-detect register, which signals the
interrupt controller to trigger IRQ level 10.

If I don’t call InterruptAttachEvent(), then I can see that a falling
edge is detected in the GEDR1 register. However, if
InterruptAttachEvent() is called, then it appears that the OS is
clearing the bit in the GEDR1 register upon interrupt, but fails to
send a pulse to the ISR thread.

It is noteworthy that I am running the SMC Ethernet driver, which
shares IRQ level 10 with the CAN controller. On the XScale, level 10
is shared by GPIO pins 2-80. In general, I believe that sharing
interrupt levels is permitted in QNX.

Does anyone know why I am not seeing a pulse when the interrupt line
goes low? Is there a blatant mistake that I am making here? Can anyone
suggest tools that may help diagnose this problem?

Here is a simplified version of the CAN driver that shows how things
are being set up:

I am compiling like this:

qcc -Vgcc_ntoarmle -Wall testint.c -o testint

################################################################
#include <errno.h>
#include <stddef.h>
#include <unistd.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/resmgr.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/neutrino.h>

#define CAN_IRQ 10

#define PULSE_CODE_INT _PULSE_CODE_MINAVAIL + 2

#define GPIO_BASE_ADDR 0x40e00000
#define GPIO_IO_SPACE_LEN 0x6c
#define GPLR1 1
#define GPDR1 4
#define GRER1 13
#define GFER1 16
#define GEDR1 19
#define GAFR1_U 24

#define INT_CTLR_BASE_ADDR 0x40d00000
#define INT_CTLR_IO_SPACE_LEN 0x18
#define ICIP 0
#define ICMR 1
#define ICLR 2
#define ICFP 3
#define ICPR 4
#define ICCR 5

typedef unsigned char u8;

static volatile uint32_t *gpioBase = NULL; // base memory for our
GPIO
static volatile uint32_t *intBase = NULL; // base memory for
interrupt regs
static struct sigevent intEvent; // pulse to start Tx or
Rx
static struct _pulse receiveMsg; // location for receing
messages
static int channelID; // ID of channel for CAN
thread
static int connectionID; // ID of connection for
CAN thread
static int interruptID = -1;


int main (int argc, char **argv)
{
int sts;
int rcvid;

// map memory for gpio registers
gpioBase = mmap_device_memory(0, GPIO_IO_SPACE_LEN,
PROT_READ | PROT_WRITE |
PROT_NOCACHE,
0, GPIO_BASE_ADDR);
if (gpioBase == MAP_FAILED)
{
fprintf(stderr, “CAN: Unable to map memory for GPIO
registers\n”);
return EXIT_FAILURE;
}

// map memory for interrupt controller registers
intBase = mmap_device_memory(0, INT_CTLR_IO_SPACE_LEN,
PROT_READ | PROT_WRITE |
PROT_NOCACHE,
0, INT_CTLR_BASE_ADDR);
if (intBase == MAP_FAILED)
{
fprintf(stderr, “CAN: Unable to map memory for interrupt
registers\n”);
return EXIT_FAILURE;
}

// initialize GPIO registers for pin 53
gpioBase[GPDR1] &= ~(1 << 21); // set as an input
gpioBase[GEDR1] = (1 << 21); // clear edge detect status
gpioBase[GFER1] |= (1 << 21); // detect falling edge
gpioBase[GAFR1_U] &= ~(3 << 10); // select GPIO function

// initialize interrupt controller registers for
// level 10 (GPIO[80:2] edge-detect)
intBase[ICLR] &= ~(1 << 10); // route level 10 to IRQ
intBase[ICMR] |= (1 << 10); // unmask level 10

// enable I/O privity
sts = ThreadCtl(_NTO_TCTL_IO, NULL);
if (sts != EOK)
{
fprintf(stderr, “CAN: Can’t get IO privity\n”);
}

// tell the OS to send a pulse upon interrupt
channelID = ChannelCreate(_NTO_CHF_UNBLOCK);
connectionID = ConnectAttach(0, 0, channelID, _NTO_SIDE_CHANNEL,
0);
SIGEV_PULSE_INIT(&intEvent, connectionID,
SIGEV_PULSE_PRIO_INHERIT, PULSE_CODE_INT, NULL);
interruptID = InterruptAttachEvent(CAN_IRQ, &intEvent,
_NTO_INTR_FLAGS_TRK_MSK);
if (interruptID == -1)
{
fprintf(stderr, “CAN: Error in InterruptAttach()\n”);
}

// main loop - listen for interrupt pulses
while (1)
{
rcvid = MsgReceive(channelID, &receiveMsg, sizeof(receiveMsg),
NULL);
if (rcvid == 0)
{
switch (receiveMsg.code)
{
case PULSE_CODE_INT:
printf("***Got an interrupt\n");
InterruptUnmask(CAN_IRQ, interruptID);
break;

default:
fprintf(stderr, “CAN: Unrecognized pulse\n”);
break;
}
}
else
{
fprintf(stderr, “CAN: Got something other than a
pulse\n”);
}
}
}

Thanks in advance for any help.
-Steve

Hi Steven,

Did you try to handle interrupt events in way as it described in doc?

http://www.qnx.com/developer/docs/momentics_nc_docs/neutrino/prog/inthandler.html

Here is small example, it works for me on x86 :


int main(void) {

struct sigevent event;
int intr_id;

//Check for root privilegies and notificate the kernal
if( ThreadCtl(_NTO_TCTL_IO, 0) == -1 ) {
printf(“Process doesn’t have superuser capabilities.\n”);
return EXIT_FAILURE;
}

//Check out the hardware
//…


//Attach interrupt event
SIGEV_INTR_INIT(&event);
intr_id=InterruptAttachEvent(CAN_IRQ, &event, _NTO_INTR_FLAGS_END);

//Clear pending interrupts if required
//…

//Enable interrupts from hardware
//…

//Wait for interrupt event
while(1) {
InterruptWait(0,NULL);

//Read status for checking intr requester
//if it is my request clear interrupt request from hardware as well
//…

//Unmask interrupt (its masked by system for us)
InterruptUnmask(CAN_IRQ, intr_id);

//Do all interrupt stuff here
//…

//…
//End of main
return EXIT_SUCCESS;
}


Eduard.
ed1k at ukr dot net

Steven R. Lilly <lillyste@yahoo.com> wrote in article
<fae6e8db.0207191254.63011a59@posting.google.com>…

I am using QNX Neutrino 6.1.0 on an Intel XScale PXA210 (Sabinal)
applications processor.

I am attempting to use the InterruptAttachEvent() function to field
interrupts coming from a CAN controller on GPIO pin 53 of the XScale
processor. When the interrupt pin transitions from high to low, a bit
should be set in the GPIO edge-detect register, which signals the
interrupt controller to trigger IRQ level 10.
[…]

Hi Steve,

Did you enable the GPIO interrupt properly in the startup? Check out
init_intrinfo.c, also note the globals being used to track the interrupt
enable state.

Regards,
John Roul

“Steven R. Lilly” <lillyste@yahoo.com> wrote in message
news:fae6e8db.0207191254.63011a59@posting.google.com

I am using QNX Neutrino 6.1.0 on an Intel XScale PXA210 (Sabinal)
applications processor.

I am attempting to use the InterruptAttachEvent() function to field
interrupts coming from a CAN controller on GPIO pin 53 of the XScale
processor. When the interrupt pin transitions from high to low, a bit
should be set in the GPIO edge-detect register, which signals the
interrupt controller to trigger IRQ level 10.

If I don’t call InterruptAttachEvent(), then I can see that a falling
edge is detected in the GEDR1 register. However, if
InterruptAttachEvent() is called, then it appears that the OS is
clearing the bit in the GEDR1 register upon interrupt, but fails to
send a pulse to the ISR thread.

It is noteworthy that I am running the SMC Ethernet driver, which
shares IRQ level 10 with the CAN controller. On the XScale, level 10
is shared by GPIO pins 2-80. In general, I believe that sharing
interrupt levels is permitted in QNX.

Does anyone know why I am not seeing a pulse when the interrupt line
goes low? Is there a blatant mistake that I am making here? Can anyone
suggest tools that may help diagnose this problem?

Here is a simplified version of the CAN driver that shows how things
are being set up:

I am compiling like this:

qcc -Vgcc_ntoarmle -Wall testint.c -o testint

################################################################
#include <errno.h
#include <stddef.h
#include <unistd.h
#include <sys/iofunc.h
#include <sys/dispatch.h
#include <string.h
#include <stdio.h
#include <stdlib.h
#include <pthread.h
#include <sys/resmgr.h
#include <fcntl.h
#include <sys/mman.h
#include <sys/neutrino.h

#define CAN_IRQ 10

#define PULSE_CODE_INT _PULSE_CODE_MINAVAIL + 2

#define GPIO_BASE_ADDR 0x40e00000
#define GPIO_IO_SPACE_LEN 0x6c
#define GPLR1 1
#define GPDR1 4
#define GRER1 13
#define GFER1 16
#define GEDR1 19
#define GAFR1_U 24

#define INT_CTLR_BASE_ADDR 0x40d00000
#define INT_CTLR_IO_SPACE_LEN 0x18
#define ICIP 0
#define ICMR 1
#define ICLR 2
#define ICFP 3
#define ICPR 4
#define ICCR 5

typedef unsigned char u8;

static volatile uint32_t *gpioBase = NULL; // base memory for our
GPIO
static volatile uint32_t *intBase = NULL; // base memory for
interrupt regs
static struct sigevent intEvent; // pulse to start Tx or
Rx
static struct _pulse receiveMsg; // location for receing
messages
static int channelID; // ID of channel for CAN
thread
static int connectionID; // ID of connection for
CAN thread
static int interruptID = -1;


int main (int argc, char **argv)
{
int sts;
int rcvid;

// map memory for gpio registers
gpioBase = mmap_device_memory(0, GPIO_IO_SPACE_LEN,
PROT_READ | PROT_WRITE |
PROT_NOCACHE,
0, GPIO_BASE_ADDR);
if (gpioBase == MAP_FAILED)
{
fprintf(stderr, “CAN: Unable to map memory for GPIO
registers\n”);
return EXIT_FAILURE;
}

// map memory for interrupt controller registers
intBase = mmap_device_memory(0, INT_CTLR_IO_SPACE_LEN,
PROT_READ | PROT_WRITE |
PROT_NOCACHE,
0, INT_CTLR_BASE_ADDR);
if (intBase == MAP_FAILED)
{
fprintf(stderr, “CAN: Unable to map memory for interrupt
registers\n”);
return EXIT_FAILURE;
}

// initialize GPIO registers for pin 53
gpioBase[GPDR1] &= ~(1 << 21); // set as an input
gpioBase[GEDR1] = (1 << 21); // clear edge detect status
gpioBase[GFER1] |= (1 << 21); // detect falling edge
gpioBase[GAFR1_U] &= ~(3 << 10); // select GPIO function

// initialize interrupt controller registers for
// level 10 (GPIO[80:2] edge-detect)
intBase[ICLR] &= ~(1 << 10); // route level 10 to IRQ
intBase[ICMR] |= (1 << 10); // unmask level 10

// enable I/O privity
sts = ThreadCtl(_NTO_TCTL_IO, NULL);
if (sts != EOK)
{
fprintf(stderr, “CAN: Can’t get IO privity\n”);
}

// tell the OS to send a pulse upon interrupt
channelID = ChannelCreate(_NTO_CHF_UNBLOCK);
connectionID = ConnectAttach(0, 0, channelID, _NTO_SIDE_CHANNEL,
0);
SIGEV_PULSE_INIT(&intEvent, connectionID,
SIGEV_PULSE_PRIO_INHERIT, PULSE_CODE_INT, NULL);
interruptID = InterruptAttachEvent(CAN_IRQ, &intEvent,
_NTO_INTR_FLAGS_TRK_MSK);
if (interruptID == -1)
{
fprintf(stderr, “CAN: Error in InterruptAttach()\n”);
}

// main loop - listen for interrupt pulses
while (1)
{
rcvid = MsgReceive(channelID, &receiveMsg, sizeof(receiveMsg),
NULL);
if (rcvid == 0)
{
switch (receiveMsg.code)
{
case PULSE_CODE_INT:
printf("***Got an interrupt\n");
InterruptUnmask(CAN_IRQ, interruptID);
break;

default:
fprintf(stderr, “CAN: Unrecognized pulse\n”);
break;
}
}
else
{
fprintf(stderr, “CAN: Got something other than a
pulse\n”);
}
}
}

Thanks in advance for any help.
-Steve