Chapter 19. Device Driver Interface to the Kernel
Table of Contents
- 19.1. Interrupt Model
- 19.2. Synchronization
- 19.3. SMP Support
- 19.4. Device Driver Models
- 19.5. Synchronization Levels
- 19.6. The API
- 19.6.1. cyg_drv_isr_lock
- 19.6.2. cyg_drv_isr_unlock
- 19.6.3. cyg_drv_spinlock_init
- 19.6.4. cyg_drv_spinlock_destroy
- 19.6.5. cyg_drv_spinlock_spin
- 19.6.6. cyg_drv_spinlock_clear
- 19.6.7. cyg_drv_spinlock_try
- 19.6.8. cyg_drv_spinlock_test
- 19.6.9. cyg_drv_spinlock_spin_intsave
- 19.6.10. cyg_drv_spinlock_clear_intsave
- 19.6.11. cyg_drv_dsr_lock
- 19.6.12. cyg_drv_dsr_unlock
- 19.6.13. cyg_drv_mutex_init
- 19.6.14. cyg_drv_mutex_destroy
- 19.6.15. cyg_drv_mutex_lock
- 19.6.16. cyg_drv_mutex_trylock
- 19.6.17. cyg_drv_mutex_unlock
- 19.6.18. cyg_drv_mutex_release
- 19.6.19. cyg_drv_cond_init
- 19.6.20. cyg_drv_cond_destroy
- 19.6.21. cyg_drv_cond_wait
- 19.6.22. cyg_drv_cond_signal
- 19.6.23. cyg_drv_cond_broadcast
- 19.6.24. cyg_drv_interrupt_create
- 19.6.25. cyg_drv_interrupt_delete
- 19.6.26. cyg_drv_interrupt_attach
- 19.6.27. cyg_drv_interrupt_detach
- 19.6.28. cyg_drv_interrupt_mask
- 19.6.29. cyg_drv_interrupt_mask_intunsafe
- 19.6.30. cyg_drv_interrupt_unmask
- 19.6.31. cyg_drv_interrupt_unmask_intunsafe
- 19.6.32. cyg_drv_interrupt_acknowledge
- 19.6.33. cyg_drv_interrupt_configure
- 19.6.34. cyg_drv_interrupt_level
- 19.6.35. cyg_drv_interrupt_set_cpu
- 19.6.36. cyg_drv_interrupt_get_cpu
- 19.6.37. cyg_ISR_t
- 19.6.38. cyg_DSR_t
- 19.7. Instrumentation
This chapter describes the API that device drivers may use to interact with the kernel and HAL. It is primarily concerned with the control and management of interrupts and the synchronization of ISRs, DSRs and threads.
The same API will be present in configurations where the kernel is not present. In this case the functions will be supplied by code acting directly on the HAL.
19.1. Interrupt Model
eCos presents a three level interrupt model to device drivers. This consists of Interrupt Service Routines (ISRs) that are invoked in response to a hardware interrupt; Deferred Service Routines (DSRs) that are invoked in response to a request by an ISR; and threads that are the clients of the driver.
Hardware interrupts are delivered with minimal intervention to an ISR. The HAL decodes the hardware source of the interrupt and calls the ISR of the attached interrupt object. This ISR may manipulate the hardware but is only allowed to make a restricted set of calls on the driver API. When it returns, an ISR may request that its DSR should be scheduled to run.
A DSR will be run when it is safe to do so without interfering with
the scheduler. Most of the time the DSR will run immediately after the
ISR, but if the current thread is in the scheduler, it will be delayed
until the thread is finished. A DSR is allowed to make a larger set of
driver API calls, including, in particular, being able to call
cyg_drv_cond_signal()
to wake up waiting
threads.
Finally, threads are able to make all API calls and in particular are allowed to wait on mutexes and condition variables.
For a device driver to receive interrupts it must first define ISR and
DSR routines as shown below, and then call
cyg_drv_interrupt_create()
. Using the handle
returned, the driver must then call
cyg_drv_interrupt_attach()
to actually attach the
interrupt to the hardware vector.
19.2. Synchronization
There are three levels of synchronization supported:
-
Synchronization with ISRs. This normally means disabling
interrupts to prevent the ISR running during a critical
section. In an SMP environment, this will also require the use of
a spinlock to synchronize with ISRs, DSRs or threads running on
other CPUs. This is implemented by the
cyg_drv_isr_lock()
andcyg_drv_isr_unlock()
functions. This mechanism should be used sparingly and for short periods only. For finer grained synchronization, individual spinlocks are also supplied. -
Synchronization with DSRs. This will be implemented in the kernel
by taking the scheduler lock to prevent DSRs running during
critical sections. In non-kernel configurations it will be
implemented by non-kernel code. This is implemented by the
cyg_drv_dsr_lock()
andcyg_drv_dsr_unlock()
functions. As with ISR synchronization, this mechanism should be used sparingly. Only DSRs and threads may use this synchronization mechanism, ISRs are not allowed to do this. - Synchronization with threads. This is implemented with mutexes and condition variables. Only threads may lock the mutexes and wait on the condition variables, although DSRs may signal condition variables.
Any data that is accessed from more than one level must be protected against concurrent access. Data that is accessed by ISRs must be protected with the ISR lock, or a spinlock at all times, even in ISRs. Data that is shared between DSRs and threads should be protected with the DSR lock. Data that is only accessed by threads must be protected with mutexes.
19.3. SMP Support
Some eCos targets contain support for Symmetric Multi-Processing (SMP) configurations, where more than one CPU may be present. This option has a number of ramifications for the way in which device drivers must be written if they are to be SMP-compatible.
Since it is possible for the ISR, DSR and thread components of a device driver to execute on different CPUs, it is important that SMP-compatible device drivers use the driver API routines correctly.
Synchronization between threads and DSRs continues to require that the
thread-side code use cyg_drv_dsr_lock()
and
cyg_drv_dsr_unlock()
to protect access to shared
data. While it is not strictly necessary for DSR code to claim the DSR
lock, since DSRs are run with it claimed already, it is good practice
to do so.
Synchronization between ISRs and DSRs or threads requires that access
to sensitive data be protected, in all places, by calls to
cyg_drv_isr_lock()
and
cyg_drv_isr_unlock()
. Disabling or masking
interrupts is not adequate, since the thread or DSR may be running on
a different CPU and interrupt enable/disable only work on the current
CPU.
The ISR lock, for SMP systems, not only disables local interrupts, but also acquires a spinlock to protect against concurrent access from other CPUs. This is necessary because ISRs are not run with the scheduler lock claimed. Hence they can run in parallel with the other components of the device driver.
The ISR lock provided by the driver API is just a shared spinlock that
is available for use by all drivers. If a driver needs to implement a
finer grain of locking, it can use private spinlocks, accessed via the
cyg_drv_spinlock_*()
functions.
19.4. Device Driver Models
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.
19.5. Synchronization Levels
Since it would be dangerous for an ISR or DSR to make a call that might reschedule the current thread (by trying to lock a mutex for example) all functions in this API have an associated synchronization level. These levels are:
- Thread
- This function may only be called from within threads. This is usually the client code that makes calls into the device driver. In a non-kernel configuration, this will be code running at the default non-interrupt level.
- DSR
- This function may be called by either DSR or thread code.
- ISR
- This function may be called from ISR, DSR or thread code.
The following table shows, for each API function, the levels at which is may be called:
Callable from: Function ISR DSR Thread ------------------------------------------------------------------------- cyg_drv_isr_lock X X X cyg_drv_isr_unlock X X X cyg_drv_spinlock_init X cyg_drv_spinlock_destroy X cyg_drv_spinlock_spin X X X cyg_drv_spinlock_clear X X X cyg_drv_spinlock_try X X X cyg_drv_spinlock_test X X X cyg_drv_spinlock_spin_intsave X X X cyg_drv_spinlock_clear_intsave X X X cyg_drv_dsr_lock X X cyg_drv_dsr_unlock X X cyg_drv_mutex_init X cyg_drv_mutex_destroy X cyg_drv_mutex_lock X cyg_drv_mutex_trylock X cyg_drv_mutex_unlock X cyg_drv_mutex_release X cyg_drv_cond_init X cyg_drv_cond_destroy X cyg_drv_cond_wait X cyg_drv_cond_signal X X cyg_drv_cond_broadcast X X cyg_drv_interrupt_create X cyg_drv_interrupt_delete X cyg_drv_interrupt_attach X X X cyg_drv_interrupt_detach X X X cyg_drv_interrupt_mask X X X cyg_drv_interrupt_unmask X X X cyg_drv_interrupt_acknowledge X X X cyg_drv_interrupt_configure X X X cyg_drv_interrupt_level X X X cyg_drv_interrupt_set_cpu X X X cyg_drv_interrupt_get_cpu X X X
19.6. The API
- 19.6.1. cyg_drv_isr_lock
- 19.6.2. cyg_drv_isr_unlock
- 19.6.3. cyg_drv_spinlock_init
- 19.6.4. cyg_drv_spinlock_destroy
- 19.6.5. cyg_drv_spinlock_spin
- 19.6.6. cyg_drv_spinlock_clear
- 19.6.7. cyg_drv_spinlock_try
- 19.6.8. cyg_drv_spinlock_test
- 19.6.9. cyg_drv_spinlock_spin_intsave
- 19.6.10. cyg_drv_spinlock_clear_intsave
- 19.6.11. cyg_drv_dsr_lock
- 19.6.12. cyg_drv_dsr_unlock
- 19.6.13. cyg_drv_mutex_init
- 19.6.14. cyg_drv_mutex_destroy
- 19.6.15. cyg_drv_mutex_lock
- 19.6.16. cyg_drv_mutex_trylock
- 19.6.17. cyg_drv_mutex_unlock
- 19.6.18. cyg_drv_mutex_release
- 19.6.19. cyg_drv_cond_init
- 19.6.20. cyg_drv_cond_destroy
- 19.6.21. cyg_drv_cond_wait
- 19.6.22. cyg_drv_cond_signal
- 19.6.23. cyg_drv_cond_broadcast
- 19.6.24. cyg_drv_interrupt_create
- 19.6.25. cyg_drv_interrupt_delete
- 19.6.26. cyg_drv_interrupt_attach
- 19.6.27. cyg_drv_interrupt_detach
- 19.6.28. cyg_drv_interrupt_mask
- 19.6.29. cyg_drv_interrupt_mask_intunsafe
- 19.6.30. cyg_drv_interrupt_unmask
- 19.6.31. cyg_drv_interrupt_unmask_intunsafe
- 19.6.32. cyg_drv_interrupt_acknowledge
- 19.6.33. cyg_drv_interrupt_configure
- 19.6.34. cyg_drv_interrupt_level
- 19.6.35. cyg_drv_interrupt_set_cpu
- 19.6.36. cyg_drv_interrupt_get_cpu
- 19.6.37. cyg_ISR_t
- 19.6.38. cyg_DSR_t
This section details the Driver Kernel Interface. Note that most of these functions are identical to Kernel C API calls, and will in most configurations be wrappers for them. In non-kernel configurations they will be supported directly by the HAL, or by code to emulate the required behavior.
This API is defined in the header file
<cyg/hal/drv_api.h>
.
19.6.1. cyg_drv_isr_lock
- Function:
void cyg_drv_isr_lock()
- Arguments:
- None
- Result:
- None
- Level:
- ISR
- Description:
- Disables delivery of interrupts, preventing all ISRs running. This function maintains a counter of the number of times it is called.
19.6.2. cyg_drv_isr_unlock
- Function:
void cyg_drv_isr_unlock()
- Arguments:
- None
- Result:
- None
- Level:
- ISR
- Description:
-
Re-enables delivery of interrupts, allowing ISRs to
run. This function decrements the counter maintained by
cyg_drv_isr_lock()
, and only re-allows interrupts when it goes to zero.
19.6.3. cyg_drv_spinlock_init
- Function:
void cyg_drv_spinlock_init(cyg_spinlock_t *lock, cyg_bool_t locked )
- Arguments:
lock
- pointer to spinlock to initializelocked
- initial state of lock- Result:
- None
- Level:
- Thread
- Description:
-
Initialize a spinlock. The
locked
argument indicates how the spinlock should be initialized:TRUE
for locked orFALSE
for unlocked state.
19.6.4. cyg_drv_spinlock_destroy
- Function:
void cyg_drv_spinlock_destroy(cyg_spinlock_t *lock )
- Arguments:
lock
- pointer to spinlock destroy- Result:
- None
- Level:
- Thread
- Description:
- Destroy a spinlock that is no longer of use. There should be no CPUs attempting to claim the lock at the time this function is called, otherwise the behavior is undefined.
19.6.5. cyg_drv_spinlock_spin
- Function:
void cyg_drv_spinlock_spin(cyg_spinlock_t *lock )
- Arguments:
lock
- pointer to spinlock to claim- Result:
- None
- Level:
- ISR
- Description:
-
Claim a spinlock, waiting in a busy loop until it is
available. Wherever this is called from, this operation
effectively pauses the CPU until it succeeds. This operations
should therefore be used sparingly, and in situations where
deadlocks/livelocks cannot occur. Also see
cyg_drv_spinlock_spin_intsave()
.
19.6.6. cyg_drv_spinlock_clear
- Function:
void cyg_drv_spinlock_clear(cyg_spinlock_t *lock )
- Arguments:
lock
- pointer to spinlock to clear- Result:
- None
- Level:
- ISR
- Description:
-
Clear a spinlock. This clears the spinlock and allows another
CPU to claim it. If there is more than one CPU waiting in
cyg_drv_spinlock_spin()
then just one of them will be allowed to proceed.
19.6.7. cyg_drv_spinlock_try
- Function:
cyg_bool_t cyg_drv_spinlock_try(cyg_spinlock_t *lock )
- Arguments:
lock
- pointer to spinlock to try- Result:
-
TRUE
if the spinlock was claimed,FALSE
otherwise. - Level:
- ISR
- Description:
-
Try to claim the spinlock without waiting. If the spinlock could
be claimed immediately then
TRUE
is returned. If the spinlock is already claimed then the result isFALSE
.
19.6.8. cyg_drv_spinlock_test
- Function:
cyg_bool_t cyg_drv_spinlock_test(cyg_spinlock_t *lock )
- Arguments:
lock
- pointer to spinlock to test- Result:
-
TRUE
if the spinlock is available,FALSE
otherwise. - Level:
- ISR
- Description:
-
Inspect the state of the spinlock. If the spinlock is not locked
then the result is
TRUE
. If it is locked then the result will beFALSE
.
19.6.9. cyg_drv_spinlock_spin_intsave
- Function:
void cyg_drv_spinlock_spin_intsave( cyg_spinlock_t *lock, cyg_addrword_t *istate )
- Arguments:
lock
- pointer to spinlock to claimistate
- pointer to interrupt state save location- Result:
- None
- Level:
- ISR
- Description:
This function behaves exactly like
cyg_drv_spinlock_spin()
except that it also disables interrupts before attempting to claim the lock. The current interrupt enable state is saved in*istate
. Interrupts remain disabled once the spinlock had been claimed and must be restored by callingcyg_drv_spinlock_clear_intsave()
.In general, device drivers should use this function to claim and release spinlocks rather than the non-
_intsave()
variants, to ensure proper exclusion with code running on both other CPUs and this CPU.
19.6.10. cyg_drv_spinlock_clear_intsave
- Function:
void cyg_drv_spinlock_clear_intsave( cyg_spinlock_t *lock, cyg_addrword_t istate )
- Arguments:
lock
- pointer to spinlock to clearistate
- interrupt state to restore- Result:
- None
- Level:
- ISR
- Description:
-
This function behaves exactly like
cyg_drv_spinlock_clear()
except that it also restores an interrupt state saved bycyg_drv_spinlock_spin_intsave()
. Theistate
argument must have been initialized by a previous call tocyg_drv_spinlock_spin_intsave()
.
19.6.11. cyg_drv_dsr_lock
- Function:
void cyg_drv_dsr_lock()
- Arguments:
- None
- Result:
- None
- Level:
- DSR
- Description:
- Disables scheduling of DSRs. This function maintains a counter of the number of times it has been called.
19.6.12. cyg_drv_dsr_unlock
- Function:
void cyg_drv_dsr_unlock()
- Arguments:
- None
- Result:
None
- Level:
- DSR
- Description:
-
Re-enables scheduling of DSRs. This function decrements
the counter incremented by
cyg_drv_dsr_lock()
. DSRs are only allowed to be delivered when the counter goes to zero.
19.6.13. cyg_drv_mutex_init
- Function:
void cyg_drv_mutex_init(cyg_drv_mutex_t *mutex)
- Arguments:
mutex
- pointer to mutex to initialize- Result:
- None
- Level:
- Thread
- Description:
-
Initialize the mutex pointed to by the
mutex
argument.
19.6.14. cyg_drv_mutex_destroy
- Function:
void cyg_drv_mutex_destroy( cyg_drv_mutex_t *mutex )
- Arguments:
mutex
- pointer to mutex to destroy- Result:
- None
- Level:
- Thread
- Description:
-
Destroy the mutex pointed to by the
mutex
argument. The mutex should be unlocked and there should be no threads waiting to lock it when this call in made.
19.6.15. cyg_drv_mutex_lock
- Function:
cyg_bool cyg_drv_mutex_lock( cyg_drv_mutex_t *mutex )
- Arguments:
mutex
- pointer to mutex to lock- Result:
-
TRUE
it the thread has claimed the lock,FALSE
otherwise. - Level:
- Thread
- Description:
-
Attempt to lock the mutex pointed to by the
mutex
argument. If the mutex is already locked by another thread then this thread will wait until that thread is finished. If the result from this function isFALSE
then the thread was broken out of its wait by some other thread. In this case the mutex will not have been locked.
19.6.16. cyg_drv_mutex_trylock
- Function:
cyg_bool cyg_drv_mutex_trylock( cyg_drv_mutex_t *mutex )
- Arguments:
mutex
- pointer to mutex to lock- Result:
-
TRUE
if the mutex has been locked,FALSE
otherwise. - Level:
- Thread
- Description:
-
Attempt to lock the mutex pointed to by the
mutex
argument without waiting. If the mutex is already locked by some other thread then this function returnsFALSE
. If the function can lock the mutex without waiting, thenTRUE
is returned.
19.6.17. cyg_drv_mutex_unlock
- Function:
void cyg_drv_mutex_unlock( cyg_drv_mutex_t *mutex )
- Arguments:
mutex
- pointer to mutex to unlock- Result:
- None
- Level:
- Thread
- Description:
-
Unlock the mutex pointed to by the
mutex
argument. If there are any threads waiting to claim the lock, one of them is woken up to try and claim it.
19.6.18. cyg_drv_mutex_release
- Function:
void cyg_drv_mutex_release( cyg_drv_mutex_t *mutex )
- Arguments:
mutex
- pointer to mutex to release- Result:
- None
- Level:
- Thread
- Description:
-
Release all threads waiting on the mutex pointed to by the
mutex
argument. These threads will return fromcyg_drv_mutex_lock()
with aFALSE
result and will not have claimed the mutex. This function has no effect on any thread that may have the mutex claimed.
19.6.19. cyg_drv_cond_init
- Function:
void cyg_drv_cond_init( cyg_drv_cond_t *cond, cyg_drv_mutex_t *mutex )
- Arguments:
cond
- condition variable to initializemutex
- mutex to associate with this condition variable- Result:
- None
- Level:
- Thread
- Description:
-
Initialize the condition variable pointed to by the
cond
argument. Themutex
argument must point to a mutex with which this condition variable is associated. A thread may only wait on this condition variable when it has already locked the associated mutex. Waiting will cause the mutex to be unlocked, and when the thread is reawakened, it will automatically claim the mutex before continuing.
19.6.20. cyg_drv_cond_destroy
- Function:
void cyg_drv_cond_destroy( cyg_drv_cond_t *cond )
- Arguments:
cond
- condition variable to destroy- Result:
- None
- Level:
- Thread
- Description:
-
Destroy the condition variable pointed to by the
cond
argument.
19.6.21. cyg_drv_cond_wait
- Function:
void cyg_drv_cond_wait( cyg_drv_cond_t *cond )
- Arguments:
cond
- condition variable to wait on- Result:
- None
- Level:
- Thread
- Description:
-
Wait for a signal on the condition variable pointed to by
the
cond
argument. The thread must have locked the associated mutex, supplied incyg_drv_cond_init()
, before waiting on this condition variable. While the thread waits, the mutex will be unlocked, and will be re-locked before this function returns. It is possible for threads waiting on a condition variable to occasionally wake up spuriously. For this reason it is necessary to use this function in a loop that re-tests the condition each time it returns. Note that this function performs an implicit scheduler unlock/relock sequence, so that it may be used within an explicitcyg_drv_dsr_lock()…cyg_drv_dsr_unlock()
structure.
19.6.22. cyg_drv_cond_signal
- Function:
void cyg_drv_cond_signal( cyg_drv_cond_t *cond )
- Arguments:
cond
- condition variable to signal- Result:
- None
- Level:
- DSR
- Description:
-
Signal the condition variable pointed to by the
cond
argument. If there are any threads waiting on this variable at least one of them will be awakened. Note that in some configurations there may not be any difference between this function andcyg_drv_cond_broadcast()
.
19.6.23. cyg_drv_cond_broadcast
- Function:
void cyg_drv_cond_broadcast( cyg_drv_cond_t *cond )
- Arguments:
cond
- condition variable to broadcast to- Result:
- None
- Level:
- DSR
- Description:
-
Signal the condition variable pointed to by the
cond
argument. If there are any threads waiting on this variable they will all be awakened.
19.6.24. cyg_drv_interrupt_create
- Function:
void cyg_drv_interrupt_create( cyg_vector_t vector, cyg_priority_t priority, cyg_addrword_t data, cyg_ISR_t *isr, cyg_DSR_t *dsr, cyg_handle_t *handle, cyg_interrupt *intr)
- Arguments:
vector
- vector to attach topriority
- queuing prioritydata
- data pointerisr
- interrupt service routinedsr
- deferred service routinehandle
- returned handleintr
- put interrupt object here- Result:
- None
- Level:
- Thread
- Description:
Create an interrupt object and returns a handle to it. The object contains information about which interrupt vector to use and the ISR and DSR that will be called after the interrupt object is attached to the vector. The interrupt object will be allocated in the memory passed in the
intr
parameter. The interrupt object is not immediately attached; it must be attached with thecyg_interrupt_attach()
call.The
data
argument will be passed to both the registered ISR and DSR. Typically it will be a pointer to some data structure.
19.6.25. cyg_drv_interrupt_delete
- Function:
void cyg_drv_interrupt_delete( cyg_handle_t interrupt )
- Arguments:
interrupt
- interrupt to delete- Result:
- None
- Level:
- Thread
- Description:
-
Detach the interrupt from the vector and free the memory
passed in the
intr
argument tocyg_drv_interrupt_create()
for reuse.
19.6.26. cyg_drv_interrupt_attach
- Function:
void cyg_drv_interrupt_attach( cyg_handle_t interrupt )
- Arguments:
interrupt
- interrupt to attach- Result:
- None
- Level:
- ISR
- Description:
- Attach the interrupt to the vector so that interrupts will be delivered to the ISR when the interrupt occurs.
19.6.27. cyg_drv_interrupt_detach
- Function:
void cyg_drv_interrupt_detach( cyg_handle_t interrupt )
- Arguments:
interrupt
- interrupt to detach- Result:
- None
- Level:
- ISR
- Description:
- Detach the interrupt from the vector so that interrupts will no longer be delivered to the ISR.
19.6.28. cyg_drv_interrupt_mask
- Function:
void cyg_drv_interrupt_mask(cyg_vector_t vector )
- Arguments:
vector
- vector to mask- Result:
- None
- Level:
- ISR
- Description:
- Program the interrupt controller to stop delivery of interrupts on the given vector. On architectures which implement interrupt priority levels this may also disable all lower priority interrupts.
19.6.29. cyg_drv_interrupt_mask_intunsafe
- Function:
void cyg_drv_interrupt_mask_intunsafe(cyg_vector_t vector )
- Arguments:
vector
- vector to mask- Result:
- None
- Level:
- ISR
- Description:
-
Program the interrupt controller to stop delivery of
interrupts on the given vector. On architectures which implement
interrupt priority levels this may also disable all lower
priority interrupts. This version differs from
cyg_drv_interrupt_mask()
in not being interrupt safe. So in situations where, for example, interrupts are already known to be disabled, this may be called to avoid the extra overhead.
19.6.30. cyg_drv_interrupt_unmask
- Function:
void cyg_drv_interrupt_unmask(cyg_vector_t vector )
- Arguments:
vector
- vector to unmask- Result:
- None
- Level:
- ISR
- Description:
-
Program the interrupt controller to re-allow delivery of
interrupts on the given
vector
.
19.6.31. cyg_drv_interrupt_unmask_intunsafe
- Function:
void cyg_drv_interrupt_unmask_intunsafe(cyg_vector_t vector )
- Arguments:
vector
- vector to unmask- Result:
- None
- Level:
- ISR
- Description:
-
Program the interrupt controller to re-allow delivery of
interrupts on the given
vector
. This version differs fromcyg_drv_interrupt_unmask()
in not being interrupt safe.
19.6.32. cyg_drv_interrupt_acknowledge
- Function:
void cyg_drv_interrupt_acknowledge( cyg_vector_t vector )
- Arguments:
vector
- vector to acknowledge- Result:
- None
- Level:
- ISR
- Description:
-
Perform any processing required at the interrupt
controller and in the CPU to cancel the current interrupt
request on the
vector
. An ISR may also need to program the hardware of the device to prevent an immediate re-triggering of the interrupt.
19.6.33. cyg_drv_interrupt_configure
- Function:
void cyg_drv_interrupt_configure( cyg_vector_t vector, cyg_bool_t level, cyg_bool_t up)
- Arguments:
vector
- vector to configurelevel
- level or edge triggeredup
- rising/falling edge, high/low level- Result:
- None
- Level:
- ISR
- Description:
-
Program the interrupt controller with the characteristics
of the interrupt source. The
level
argument chooses between level- or edge-triggered interrupts. Theup
argument chooses between high and low level for level triggered interrupts or rising and falling edges for edge triggered interrupts. This function only works with interrupt controllers that can control these parameters.
19.6.34. cyg_drv_interrupt_level
- Function:
void cyg_drv_interrupt_level( cyg_vector_t vector, cyg_priority_t level)
- Arguments:
vector
- vector to configurelevel
- level to set- Result:
- None
- Level:
- ISR
- Description:
- Program the interrupt controller to deliver the given interrupt at the supplied priority level. This function only works with interrupt controllers that can control this parameter.
19.6.35. cyg_drv_interrupt_set_cpu
- Function:
void cyg_drv_interrupt_set_cpu( cyg_vector_t vector, cyg_cpu_t cpu)
- Arguments:
vector
- interrupt vector to routecpu
- destination CPU- Result:
- None
- Level:
- ISR
- Description:
- This function causes all interrupts on the given vector to be routed to the specified CPU. Subsequently, all such interrupts will be handled by that CPU. This only works if the underlying hardware is capable of performing this kind of routing. This function does nothing on a single CPU system.
19.6.36. cyg_drv_interrupt_get_cpu
- Function:
cyg_cpu_t cyg_drv_interrupt_set_cpu( cyg_vector_t vector )
- Arguments:
vector
- interrupt vector to query- Result:
- The CPU to which this vector is routed
- Level:
- ISR
- Description:
- In multi-processor systems this function returns the id of the CPU to which interrupts on the given vector are current being delivered. In single CPU systems this function returns zero.
19.6.37. cyg_ISR_t
- Type:
typedef cyg_uint32 cyg_ISR_t( cyg_vector_t vector, cyg_addrword_t data )
- Fields:
vector
- vector being delivereddata
- data value supplied by client- Result:
- Bit mask indicating whether interrupt was handled and whether the DSR should be called.
- Description:
Interrupt Service Routine definition. A pointer to a function with this prototype is passed to
cyg_interrupt_create()
when an interrupt object is created. When an interrupt is delivered the function will be called with the vector number and the data value that was passed tocyg_interrupt_create()
.The return value is a bit mask containing one or both of the following bits:
- CYG_ISR_HANDLED
- indicates that the interrupt was handled by this ISR. It is a configuration option whether this will prevent further ISR being run.
- CYG_ISR_CALL_DSR
-
causes the DSR that was passed to
cyg_interrupt_create()
to be scheduled to be called.
19.6.38. cyg_DSR_t
- Type:
typedef void cyg_DSR_t( cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data )
- Fields:
vector
- vector being deliveredcount
- number of times DSR has been scheduleddata
- data value supplied by client- Result:
- None
- Description:
-
Deferred Service Routine prototype. A pointer to a
function with this prototype is passed to
cyg_interrupt_create()
when an interrupt object is created. When the ISR requests the scheduling of its DSR, this function will be called at some later point. In addition to thevector
anddata
arguments, which will be the same as those passed to the ISR, this routine is also passed acount
of the number of times the ISR has requested that this DSR be scheduled. This counter is zeroed each time the DSR actually runs, so it indicates how many interrupts have occurred since it last ran.
19.7. Instrumentation
If the system instrumentation support is enabled then the I/O package provides support for generating instrumentation records for various events within the general purpose I/O framework.
Instrumentation records will only be generated if the
CYGIMP_IO_INSTRUMENTATION
option is enabled, and
then only if the relevant individual event code sub-options are also
enabled. The default state is for all the instrumentation to be
disabled. Some options will generate a lot of instrumentation records
in a heavily loaded system and so care may need to be taken regarding
the instrumentation that is enabled vs the instrumentation recording
mechanism being used to avoid missing events. Depending on why the I/O
framework instrumentation is being enabled (debugging, timing
validation, etc.) the user can choose which events they wish to
record by enabling the specific CDL options.
2024-03-18 | Open Publication License |