properly handling shared-interrupts in hardware and linux-driver

hi all,

i have an interrupt-related problem on a self-designed pc104-board:

i have several int-sources connected to a register and an edge-detector. if an edge is detected an int is raised. the shared isr's then check the register to see if they need to service their device. the int is cleared by writing to the register.

my problem: sometimes no more ints are generated. reloading a driver (and thus clearing the int-request) cures this. the problem seems to be, that every isr clears the int-request (i want the drivers to be totally independent) and a new int arrives while being in the int-context. this way the int request is raised but never serviced in the system isr. with resetting the int req as late as possible in the isr's, i can reduce the window for this bug.

a solution i can think of is a state machine that queues interrupts. states would be:

idle goto wait when int raised else stay idle

wait raise int-req, wait for some cycles for a clear-int, if expiring goto idle (deactivate int), if another int-req is received goto queued

queued deassert int-req, wait for some cycles for a clear-int, if expiring raise int and goto wait, if another int is received stay queued and retrigger wait-time

this should queue and delay the int requests. the delay needs to be longer than every isr's start to clear-req time.

any other ideas?

btw, the above logic is (will) be integrated in an isplsi 1016 from lattice.

regards,

markus

Reply to
markus schorer
Loading thread data ...

Level detect is more robust than edge detect when interrupts are shared. Can you use level detect interrupts?

I am not familiar with Linux, but if you are using it, I presume that it would include some code to support shared interrupts.

If you need to write your own, can you use something like this?

InterruptDispatch: repeat acknowledge interrupt -- allows new interrupts to be latched anynew = false for all attached devices if device service request anynew = true handle device interrupt reset device request end for until not anynew return from interrupt end

Basically this stays in the dispatcher until a scan has been made with no new interrupts. The interrupt is acknowledged before testing, so that if a new request occurs after the associated device has been tested, it will trigger a new interrupt. When you exit, you know that the interrupt line has been cleared since the interrupt was acknowledged, thereby triggering a new interrupt on a new request.

Thad

Reply to
Thad Smith

the problem is, that i'm mixing an int from a ir-remote (that i can clear immediately) and i2c-devices (that i can not even service in int-context nor clear the int request). therefore i need to get an int on every edge of the int requests to be able to decide which int has been triggered and which one is queued for service. all of this is connected to a single pc104/isa interrupt.

there is support. you register several int-handlers for a single interrupt. but i can not control (nor do i know) in what sequence the handlers are executed (and who is the last one). i can not loop over all int handlers. i believe i have to get the int-reqs delayed (in hardware) until the cpu has left int-context.

this is not possible. the kernel does call every registered drivers int-handler once for every hw-int.

even your code (a far as i can see) does not handle all cases: if you get an int on device 1 while device 3 is checked ("if device service request") you won't get "anynew=true", nor receive another interrupt (as you still are in int context).

markus

Reply to
markus schorer

The repeat loop will stay active until all devices report no service needed. In what scenario do you envision a failure? I don't see any. Let's say that you get a request for device 1, service it, then get another request for device 1 when checking other devices. Since device

1 was originally serviced, anynew=true was set for that occurrence and the devices are rescanned. It is possible to exit the repeat loop with an interrupt request, but since by then the interrupt has been acknowledged and determined to have been clear, any new request will generate a new interrupt request which will cause the interrupt handler to be reentered as soon as it exits, so you won't loose the request.

As far as solving the problem in your original context, see if you can find a Linux driver guru. ;-)

Thad

Reply to
Thad Smith

i should have stressed "afaics" a bit more. you're right. ;-)

Reply to
markus schorer

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.