There are several ways in which device drivers may be built. The exact model chosen will depend on the properties of the device and the behavior desired. There are three basic models that may be adopted.
The first model is to do all device processing in the ISR. When it is
invoked the ISR programs the device hardware directly and accesses
data to be transferred directly in memory. The ISR should also call
cyg_drv_interrupt_acknowledge()
. When it is
finished it may optionally request that its DSR be invoked. The DSR
does nothing but call cyg_drv_cond_signal()
to
cause a thread to be woken up. Thread level code must call
cyg_drv_isr_lock()
, or
cyg_drv_interrupt_mask()
to prevent ISRs running
while it manipulates shared memory.
The second model is to defer device processing to the DSR. The ISR
simply prevents further delivery of interrupts by either programming
the device, or by calling
cyg_drv_interrupt_mask()
. It must then call
cyg_drv_interrupt_acknowledge()
to allow other
interrupts to be delivered and then request that its DSR be
called. When the DSR runs it does the majority of the device handling,
optionally signals a condition variable to wake a thread, and finishes
by calling cyg_drv_interrupt_unmask()
to re-allow
device interrupts. Thread level code uses
cyg_drv_dsr_lock()
to prevent DSRs running while
it manipulates shared memory. The eCos serial device drivers use this
approach.
The third model is to defer device processing even further to a
thread. The ISR behaves exactly as in the previous model and simply
blocks and acknowledges the interrupt before request that the DSR
run. The DSR itself only calls
cyg_drv_cond_signal()
to wake the thread. When
the thread awakens it performs all device processing, and has full
access to all kernel facilities while it does so. It should finish by
calling cyg_drv_interrupt_unmask()
to re-allow
device interrupts. The eCos ethernet device drivers are written to
this model.
The first model is good for devices that need immediate processing and interact infrequently with thread level. The second model trades a little latency in dealing with the device for a less intrusive synchronization mechanism. The last model allows device processing to be scheduled with other threads and permits more complex device handling.