shared interrupts, isr's and int-controller

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 ...

Why that ? IMHO a better design is setting FFs with each interrupt and resetting them by the ISR after reading them and detecting which one is set. The OR of the outputs of the FFs is the processor's interrupt source (level triggered). Thus the ISR is automatically repeated until all interrupts are serviced. The interrupt priority can be done by the ISR when selecting which of the set FFs is to be serviced.

I suppose that you are seeing a hardware or design problem.

-Michael

Reply to
Michael Schnell

the sources are really different:

- one is for a ir-remote (can be reset in int-context)

- others are int-requests of i2c devices, which i cannot service and therefore reset in int-context. triggering, resetting and servicing have to be independent. i also want the drivers for the different devices be totally independent. i would have to include a int-mask register with your design.

the general int-handling is done inside the kernel. i can't loop until all ints are cleared (can't clear at all). the driver int-handler gets a single shot on every int.

the main problem seems that i don't queue ints received in int-context. i belive this has to be resolved in hardware.

markus

Reply to
markus schorer

With level-triggered interrupts the interrupt reappears (by hardware) as long as it (here the combination of all int-sources) is cleared.

So do I. And IMHO its much easier to do this with a level-triggered design.

-Michael

Reply to
Michael Schnell

Using edge triggered interrupts can be a pain (as you are finding out), especially if you are routing more than one through to a single interrupt line.

If you use level sensitive interrupts, then you won't need to worry about the headaches that come with using edge triggered interrupts.

As you have more than one device on your custom card, you could use minor numbers to differentiate between devices, rather than having a seperate driver for each device.

HTH

Paul.

Reply to
Paul Taylor

ho would i do it? i cannot clear the devices int-request in int-context. i'm triggering a kernel-thread to do the job. it takes (at least) 8 bytes to transfer on 100kHz i2c to clear the int.

sure but that monolithic driver would be extremely large and "inhomogen". i have devices for:

- a char device (mp3-decoder with i2c-control)

- a oss-mixer (i2c-control)

- 2 radios with rds (i2c)

- 1 input-event driver (i2c)

- lirc ir-input

do you think all of this in one driver makes sense?

markus

Reply to
markus schorer

ok. how would i do this? pls. see other posts for reasons.

markus

Reply to
markus schorer

A decent hardware design should be able to do level-triggered interrupts, to be acknowledged by the ISR. If the external hardware only provides a pulse, an additional FF should help. Of course a pulse will be ignored unnoticed when it comes before the ISR acknowlages the FF.

-Michael

Reply to
Michael Schnell

See post to other thread

Depends on how many control commands you are sending to each device.

Another way possibly, you could have two levels of driver. The lowest level would deal with interrupt acknowledgement and then indicate to the higher level drivers to wake up and do something for the hardware they serve.

HTH

Regards,

Paul

Reply to
Paul Taylor

Yes

Yes

Not necessarily. One solution is :

The edge from the devices requiring servicing set the ff. The ff's are then all logically or-ed together to form a level sensitive interrupt.

The outputs from the FF's are then routed to a register for reading. When the register is read, so that the device driver can get the source of any pending interrupts, the FFs are reset at the same time by the hardware.

So now you have got the pending interrupts and have acknowledged all interrupt flags as the FF's are reset. Its also possible to use FF's that have a higher priority set than thier reset, so that if an interrupt comes along at exactly the same time that you are reading/resetting, then the interrupt is still not lost (because level sensitive) - although for the the OP's design, priorities on set/rst doesn't look like an issue.

Howvever, when I have used the above design I have implemented it in a completely synchronous design, to a local clock to the PLD/FPGA. So basically, interrupt sources would be first taken through a FF to synchronise those. The ISA bus of course, is asynchronous. But you can synchronise this up to a local FPGA clock using the ISA wait signal - it introduces a little extra delay into the bus cycle but this tends not to be noticable. Then the functionality is pretty straight forward to implement.

If there isn't a local clock to the CPLD/FPGA then then you have to bear in mind that the card may have ringing on the edges of the RD/WR signal - (depends on how well the signals have been routed), which can mean you have to think harder.

But essentially, I agree with your comment above, if the hardware is designed correctly, then level sensitive interrupts are fine, and with no loss.

However, the above probably has gone away from the OP question!

Regards,

Paul.

Reply to
Paul Taylor

ok.

i'll post the design, and you tell me what i did wrong ;-) .

see

formatting link
for the schematic. feel free to comment on the schematic, but bear in mind that i'm not doing this kind of work for money ;-) .

the relevant parts are:

- the isplsi as central control-device

- the ic9 hct541 as the isr

- the various int sources: the pcf8574, 2 saa6588 via connectors sv3 and sv4, ir_sens/irq_io ints via sv10

the isplsi and the 541 are connected to the int-reqs "in parallel". the isplsi detects edges on the int lines and sets isa_irq9 active.

each registered driver is called in an unknown sequence by the kernel, reads the isr, checks if it needs to wakeup the service-thread and writes to the isr (which deactivates the isa_irq9).

the irq_rdsx are then cleared by reading the device data in the service-thread. ints are triggered every 22ms. 8-bytes need to be transferred via 100kHz i2c (which can sleep and therefore cannot be done in int-context).

the problem is, that after some time the "isa_irq9 gets stuck": no more ints are generated, the driver hangs. i think this is related to an int being triggered while still being in int-context and not retriggering the int-req.

and: i want a single driver for a single function. nothing monolithic ...

Reply to
markus schorer

I already suggested this concept in an earlier message. But this only helps for pulses from _different_ devices. If a single device can issue interrupts too fast, you would need a kind of FIFO storing the interrupt event perhaps together with the information that caused the interrupt.

-Michael

Reply to
Michael Schnell

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.