Interrupt Handling????

I am writing a device driver.
I have two queries regarding that
When I use InterruptAttach(), the whole system hangs but if I use
InterruptAttachEvent(), there is no problem.Why?
Secondly,
My device requires

  1. Make a queue of buffers
  2. Put the start of the queue into the device register after converting this
    address into device physical address
    I am using calloc function to create queue and then use mem_offset64 () to
    convert the head address to physical address and put the address into
    register. I initialize the buffers in queue with invalid values.
    The device uses physical address of the buffers in queue to write data while
    I read using virtual address
    Now when the device has something to inform, it uses a buffer from queue to
    store data and interrupts the processor.
    I am getting interrupt but the data in the buffer is still invalid value.
    Reading device status reveals that queue is full and no interrupt has been
    serviced.
    The physical address of the queue is same as what I generated using
    mem_offset64 and the virtual address is same that I am using to read device
    interrupt data from queue. In other words, when I the physical address in
    the device register to obtain virtual address, I get same value that I am
    already using for read.
    Now my problem is if both the addresses are correct, where is the device
    actually writing? Why do not I get to see the data in the interrupt queue?

In article <ckdpoo$8rh$1@inn.qnx.com>, moreshwars@hotmail.com says…

I am writing a device driver.
I have two queries regarding that
When I use InterruptAttach(), the whole system hangs but if I use
InterruptAttachEvent(), there is no problem.Why?
Secondly,
My device requires

  1. Make a queue of buffers
  2. Put the start of the queue into the device register after converting this
    address into device physical address
    I am using calloc function

Dear Sir,
Please take a look at mmap function, particularly bring your attention
on MAP_PHYS flag as well as an example of allocation a physically
contiguous buffer from that documentation might be very useful.
http://www.qnx.com/developers/docs/momentics621
_docs/neutrino/lib_ref/m/mmap.html
Best regards,
Eduard.

Moreshwar Salpekar wrote:

When I use InterruptAttach(), the whole system hangs but if I use
InterruptAttachEvent(), there is no problem.Why?

With IA() you are living inside the interrupt chain and therefore you
are bound by the usual limits of an ISR, this includes no calls to the
OS like malloc() and no use of the FPU unless you backup the FPU
register set. It’s a good idea to not use any libraries at all.

With IAE() you are only being sent a message to say an interrupt has
occurred.

Moreshwar Salpekar <moreshwars@hotmail.com> wrote:

I am writing a device driver.
I have two queries regarding that
When I use InterruptAttach(), the whole system hangs but if I use
InterruptAttachEvent(), there is no problem.Why?

What do you do in the function that is passed to InterruptAttach()?

What you are allowed to do in there is very restricted – most
library functions can not be called from inside an interrupt
handler, and if you do so, you will crash the system.

Also, inside an interrupt handler you have a very small stack, so
don’t use very much stack. (It is the kernel’s stack, since the
kernel calls your interrupt handler.)

Also, you can’t do any floating point.

Secondly,
My device requires

  1. Make a queue of buffers
  2. Put the start of the queue into the device register after converting this
    address into device physical address
    I am using calloc function to create queue and then use mem_offset64 () to
    convert the head address to physical address and put the address into
    register. I initialize the buffers in queue with invalid values.
    The device uses physical address of the buffers in queue to write data while
    I read using virtual address
    Now when the device has something to inform, it uses a buffer from queue to
    store data and interrupts the processor.
    I am getting interrupt but the data in the buffer is still invalid value.
    Reading device status reveals that queue is full and no interrupt has been
    serviced.
    The physical address of the queue is same as what I generated using
    mem_offset64 and the virtual address is same that I am using to read device
    interrupt data from queue. In other words, when I the physical address in
    the device register to obtain virtual address, I get same value that I am
    already using for read.
    Now my problem is if both the addresses are correct, where is the device
    actually writing? Why do not I get to see the data in the interrupt queue?

If you call calloc() or any other flavour of simple allocation, the memory
isn’t promised to by physically contiguous.

As someone else noted, you want to use mmap() with special flags to
allocate physically contiguous memory. The example from the mmap()
docs is:

/* Allocate a physically contiguous buffer */
addr = mmap( 0, 262144, PROT_READ|PROT_WRITE|PROT_NOCACHE,
MAP_PHYS|MAP_ANON, NOFD, 0 );

To allocate 262144 bytes of physically contiguous memory. Then
mem_offset() or mem_offset64() will give you the physical address
that you need.

It is the combination of MAP_PHYS|MAP_ANON and NOFD that allocate
physically contiguous memory.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Dear Sir,
Thank you for the reply.
Firstly, In the ISR, I am processing the cause of interrupt by reading
device registers and in addition, it is supposed to read data coming over
the device (its an HDLC device driver). I am not doing any floating point.
In fact, I have not declared any variable float or double. I am neither
allocating memory or deallocating it, I use a preallocated buffer to read
data. I obviously have to check device registers.When using
InterruptAttachEvent(), I call the same function that should have been
called by OS Kernel. The function is exiting properly.
I have removed all printfs that I had put in to debug my driver as printf
may block in ISR or cause problems.

Secondly,
Yes I have tried using mmap yesterday and succeeded indeed. The interrupt
register and queue is being written properly now. Thanks for that to all
those who corrected that approach.

Now only thing, I have to verify read and registration with OS before I can
declare my device driver as first successful one.
I have been told that I should register my device as serial driver (each
channel separately). I am looking into that.
In addition, I also need to check why InterruptAttach brings the whole
system down.

There is another question but its regarding QNX IDE, how do I set
breakpoints and wait. I cant get it properly, though I have gone through its
documentation.
I was thinking if I could debug the driver using it from my Host PC running
on NT and target PC running QNX 6.2.1B PE. Right now I check with gdb or
using printfs (cant use it in ISR for obvious reasons).

Regards
Moreshwar
“David Gibbs” <dagibbs@qnx.com> wrote in message
news:ckgjdm$dhn$1@inn.qnx.com

Moreshwar Salpekar <> moreshwars@hotmail.com> > wrote:
I am writing a device driver.
I have two queries regarding that
When I use InterruptAttach(), the whole system hangs but if I use
InterruptAttachEvent(), there is no problem.Why?

What do you do in the function that is passed to InterruptAttach()?

What you are allowed to do in there is very restricted – most
library functions can not be called from inside an interrupt
handler, and if you do so, you will crash the system.

Also, inside an interrupt handler you have a very small stack, so
don’t use very much stack. (It is the kernel’s stack, since the
kernel calls your interrupt handler.)

Also, you can’t do any floating point.

Secondly,
My device requires

  1. Make a queue of buffers
  2. Put the start of the queue into the device register after converting
    this
    address into device physical address
    I am using calloc function to create queue and then use mem_offset64 ()
    to
    convert the head address to physical address and put the address into
    register. I initialize the buffers in queue with invalid values.
    The device uses physical address of the buffers in queue to write data
    while
    I read using virtual address
    Now when the device has something to inform, it uses a buffer from queue
    to
    store data and interrupts the processor.
    I am getting interrupt but the data in the buffer is still invalid
    value.
    Reading device status reveals that queue is full and no interrupt has
    been
    serviced.
    The physical address of the queue is same as what I generated using
    mem_offset64 and the virtual address is same that I am using to read
    device
    interrupt data from queue. In other words, when I the physical address
    in
    the device register to obtain virtual address, I get same value that I
    am
    already using for read.
    Now my problem is if both the addresses are correct, where is the device
    actually writing? Why do not I get to see the data in the interrupt
    queue?

If you call calloc() or any other flavour of simple allocation, the memory
isn’t promised to by physically contiguous.

As someone else noted, you want to use mmap() with special flags to
allocate physically contiguous memory. The example from the mmap()
docs is:

/* Allocate a physically contiguous buffer */
addr = mmap( 0, 262144, PROT_READ|PROT_WRITE|PROT_NOCACHE,
MAP_PHYS|MAP_ANON, NOFD, 0 );

To allocate 262144 bytes of physically contiguous memory. Then
mem_offset() or mem_offset64() will give you the physical address
that you need.

It is the combination of MAP_PHYS|MAP_ANON and NOFD that allocate
physically contiguous memory.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Moreshwar Salpekar <moreshwars@hotmail.com> wrote:

Dear Sir,
Thank you for the reply.
Firstly, In the ISR, I am processing the cause of interrupt by reading
device registers and in addition, it is supposed to read data coming over
the device (its an HDLC device driver). I am not doing any floating point.
In fact, I have not declared any variable float or double. I am neither
allocating memory or deallocating it, I use a preallocated buffer to read
data. I obviously have to check device registers.When using
InterruptAttachEvent(), I call the same function that should have been
called by OS Kernel. The function is exiting properly.
I have removed all printfs that I had put in to debug my driver as printf
may block in ISR or cause problems.

A printf() in the interrupt handler will definitely crash the OS.

Can you post the actual code from your ISR? That is, the ISR itself
and any/all functions that it calls?

Now only thing, I have to verify read and registration with OS before I can
declare my device driver as first successful one.
I have been told that I should register my device as serial driver (each
channel separately). I am looking into that.

Exactly how you register is, really, fairly flexible. You might not
choose to register /dev/serX, but some other descriptive device name.

One registration per channel is a reasonable choice.

There is another question but its regarding QNX IDE, how do I set
breakpoints and wait. I cant get it properly, though I have gone through its
documentation.

Without knowing what you’ve tried, it is hard to know what you missed.

  1. Can you get the IDE to visually display a breakpoint for your program
    in the editor? That is, does it display the little blue circle in the
    left margin of the editor beside the line you want to break on?

  2. Can you single-step your program? That is, can you get it to run
    in the debugger at all?

Note: you will not be able to break, or single-step through the ISR
itself, of course.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

No one seems to have said this yet. But, in general, use
InterruptAttachEvent if you can. Only use InterruptAttach if
InterruptAttachEvent is too slow. Almost always, you
can use InterruptAttachEvent.

The whole point of QNX is that you can do almost anything
you need to do in an ordinary QNX thread. It’s much easier
to debug an ordinary thread than an interrupt service
routine. You can use the debugger on a thread, You
can use print statements. And you can make system calls.

John Nagle
Team Overbot

John Nagle wrote:

No one seems to have said this yet. But, in general, use
InterruptAttachEvent if you can. Only use InterruptAttach if
InterruptAttachEvent is too slow. Almost always, you
can use InterruptAttachEvent.

Except that it only works if you have tight control of IRQ assignment.


The whole point of QNX is that you can do almost anything
you need to do in an ordinary QNX thread. It’s much easier
to debug an ordinary thread than an interrupt service
routine. You can use the debugger on a thread, You
can use print statements. And you can make system calls.

That’s mostly just a question of putting the important bits in the ISR
and passing the rest of the work off to the handler thread.

The best reason for trying to do the whole job with
InterruptAttachEvent() is what cdm said in another forum, that your code
is kept completely out of kernel space.