Project Home
Project Home
Documents
Documents
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - Unable to catch hardware interrupts: (7 Items)
   
Unable to catch hardware interrupts  
Hello.

I'm using QNX 7.1 and the platform is Intel x86_64. Two different machines - one a recent IEI TANK-610 and the other 
some obscure motherboard that I inherited a couple of years ago.

I am running in all cases as root.

When I discovered I had a problem with the TANK I decided to build up the 2nd machine and still have the problem. So I 
don't think it's to do with the TANK (a Celeron N3160 processor).

I am back to basics using some sample code I found documented with the InterruptAttachEvent() function that uses IRQ3 
(2nd UART at 0x2f8).

I killed devc-ser8250 so that I could have unfettered access to that interrupt. Didn't help. So I went to 3f8/4. No 
better. So then IRQ0 which is the timer interrupt. No good!

The same code builds and runs perfectly on my QNX 6.5 development machine.

On the 7.1 system I added a call to procmgr_ability() - but I don't think I really needed to as I'm running as root 
anyway. Whatever, it didn't help. procmgr_ability() returns EOK so I guess it's happy.

ThreadCtl(_NTO_TCTL_IO, 0) returns 0 so I guess it's happy also.

The call to InterruptAttachEvent() returns 6 so I guess it's happy.

For good measure I call InterruptEnable() but I don't think that's really required. It didn't help anyway.

InterruptWait() simply never returns regardless of IRQ used. It really surprised me that IRQ0 didn't work for me.

It doesn't work when I use InterruptAttach() either with my own handler. The handler is never called. Nowhere do I get 
any failed functions.

What might I be doing wrong in 7.1 that works fine in 6.5 (apart from the procmgr_ability() call)?  I'm sure it's simple
!

Thanks,

Geoff.

But 
Re: Unable to catch hardware interrupts  
Hi,

before kill the UART driver just use "pidin irq" and "pidin mem" to spy
and learn where the things are. May help ;-)
Apparently you have a command line access to your board on 7.1

-- Alexandre
Re: Unable to catch hardware interrupts  
> Hi,
> 
> before kill the UART driver just use "pidin irq" and "pidin mem" to spy
> and learn where the things are. May help ;-)
> Apparently you have a command line access to your board on 7.1
> 
> -- Alexandre

Hi Alexandre,

I did that. pidin -f NQ shows the IRQ's of devc-ser8250 as expected: 4 and 3 respectively.

After killing devc-ser8250 I start the example InterruptAttacheEvent() process (that I call sintr for no particular 
reason).

pidin -f NQ shows whatever IRQ I use - 0, 4, or 3.

pidin -f NQk shows all the process abilities I expected (including interruptevent).

I can build it using either the C or C++ compiler. Neither works - InterruptWait() never returns. However, in QNX6.5 
both work. No function returns a failure (typically -1)  and errno is always EOK.

I have access to the target x86_64 systems by either ssh, telnet, or local console (kbd/scn). Typically ssh.

Both are effectively PC's. The IEI TANK-610 is so called "embedded" but it's really just a "PC" reduced in physical size
 with no moving parts (big heat sink on top) powered from 12 to 36 VDC. Nothing special.

Note tat this is the first time I have attempted to catch hardware interrupts using 7.1 on an x86_64 system. I have 
however successfully been doing such things (with serial ports)  going back to the QNX2 days, right through QNX 4 and 
QNX6. Obviously 7.1 is different and I thought I had it covered. But apparently not! :-)

Geoff.

Re: Unable to catch hardware interrupts  
Hi Geoff,

My best guess is that the driver left the interrupt masked. See if an explicit call to InterruptUnmask() helps.
If that's the case then the driver may be missing the _NTO_INTR_FLAGS_TRK_MSK flag in its InterruptAttach() call.

Also, you don't need I/O privileges to use InterruptAttachEvent(), just the PROCMGR_AID_INTERRUPTEVENT ability (which 
root should have).

--Elad
Re: Unable to catch hardware interrupts  
> Hi Geoff,
> 
> My best guess is that the driver left the interrupt masked. See if an explicit
>  call to InterruptUnmask() helps.
> If that's the case then the driver may be missing the _NTO_INTR_FLAGS_TRK_MSK 
> flag in its InterruptAttach() call.
> 
> Also, you don't need I/O privileges to use InterruptAttachEvent(), just the 
> PROCMGR_AID_INTERRUPTEVENT ability (which root should have).
> 
> --Elad


Hi Elad,

I tried a call to InterruptUnmask() but it didn't help. That's when I was still playing with IRQ's 3 & 4. I didn't do 
this when I tried IRQ 0. Didn't think I'd have to.

What I don't understand is why this code using IRQ 0 works with QNX6.5 and not 7.1. I am obviously able to hook into the
 timer interrupt with no apparent consequences. Tomorrow I'll try the UART's on the 32-bit QNX 6.5 machine for 
completeness.

But if it works, while the same source when built on 7.1 doesn't (regardless of whether or not I use the C or C++ 
compiler), what else is there with IRQ 0? 

I will try the InterruptUnmask() call on IRQ's 3 and 4 tomorrow but with IRQ 0???

Cheers,

Geoff.
Re: Unable to catch hardware interrupts  
This works for the clock interrupt on a 7.1 x86_64 machine:

#include <stdio.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>

int
main(int argc, char **argv)
{
    struct sigevent ev;
    SIGEV_INTR_INIT(&ev);

    int const intr = SYSPAGE_ENTRY(qtime)->intr;
    int const id = InterruptAttachEvent(intr, &ev, _NTO_INTR_FLAGS_TRK_MSK);
    if (id == -1) {
        perror("InterruptAttachEvent");
        return 1;
    }

    for (unsigned i = 0; i < 1000; i++) {
        InterruptWait(0, NULL);
        InterruptUnmask(intr, id);
    }

    printf("Done\n");
    return 0;
}
Re: Unable to catch hardware interrupts  
> This works for the clock interrupt on a 7.1 x86_64 machine:

Indeed it does! :-)

Two lessons learnt from this exercise.

1. Don't assume the timer IRQ is 0. Use the SYSPAGE_ENTRY(qtime)->intr value! Which in my case under QNX 7.1 is IRQ2. 
But why IRQ0 worked in QNX 6.5 beats me but it threw me off. I seem to recall from the deep dim past that IRQ was a 
50mSec interrupt. QNX4? It was so long ago... I actually use SYSPAGE in some clock related routines I have but haven't 
touched them in years. So I forgot about it...

2. Make sure hardware (like UART's) you want to have generate interrupts are configured properly. In my case, I had 
forgotten that the GPO2 bit of the 16550 (8250) MCR register needs to be set.

So now I have my own version of the ser8250 driver working pretty much the way I want it.

Is there any documentation for the io-char library? I've looked but with no success.

Thanks,

Geoff.

> 
> #include <stdio.h>
> #include <sys/neutrino.h>
> #include <sys/syspage.h>
> 
> int
> main(int argc, char **argv)
> {
>     struct sigevent ev;
>     SIGEV_INTR_INIT(&ev);
> 
>     int const intr = SYSPAGE_ENTRY(qtime)->intr;
>     int const id = InterruptAttachEvent(intr, &ev, _NTO_INTR_FLAGS_TRK_MSK);
>     if (id == -1) {
>         perror("InterruptAttachEvent");
>         return 1;
>     }
> 
>     for (unsigned i = 0; i < 1000; i++) {
>         InterruptWait(0, NULL);
>         InterruptUnmask(intr, id);
>     }
> 
>     printf("Done\n");
>     return 0;
> }