Moves the Microkernel Object documentation to a new Microkernel Services section within the Kernel Primer. Labels, cross-references, figures, headings and filenames were updated to reflect the new structure. Change-Id: Ia2a91410a94caa8a97bb8211db5afc84b5dc0974 Signed-off-by: Rodrigo Caballero <rodrigo.caballero.abraham@intel.com>
152 lines
5.6 KiB
ReStructuredText
152 lines
5.6 KiB
ReStructuredText
.. _microkernel_task_irqs:
|
|
|
|
Task IRQs
|
|
#########
|
|
|
|
Concepts
|
|
********
|
|
|
|
The microkernel's task IRQ objects allow interrupts to be serviced
|
|
by tasks, rather than interrupt service routines (ISRs).
|
|
This allows a microkernel project to have task-level device drivers,
|
|
in addition to interrupt-level device drivers.
|
|
|
|
Any number of task IRQs can be defined in a microkernel system.
|
|
Each task IRQ has a numeric identifier that uniquely identifies it.
|
|
These identifiers range from 0 to N-1, where N is the total number
|
|
of task IRQs in the system.
|
|
|
|
A task that wants to service interrupts from a device
|
|
must first allocate a task IRQ and bind it to the device's interrupt source
|
|
by specifying the IRQ and interrupt priority level
|
|
assigned to that device by the system designer.
|
|
Once a task IRQ has been allocated by a task
|
|
it cannot be utilized by other tasks;
|
|
this prevents other tasks from interfering with the proper processing
|
|
of interrupts from that device.
|
|
|
|
When an interrupt is generated by the device, the kernel
|
|
runs an ISR that masks the interrupt and signals the occurrence
|
|
of the interrupt to the associated task IRQ.
|
|
The task can then use the task IRQ to recognize that
|
|
an interrupt has occurred
|
|
and then take action to service the interrupt.
|
|
At some point during interrupt servicing
|
|
the task must instruct the task IRQ to acknowledge the interrupt;
|
|
this causes the kernel to unmask the interrupt
|
|
so that future interrupts can be detected.
|
|
|
|
When a task no longer needs a task IRQ it should free the task IRQ.
|
|
This disables the interrupt associated with the task IRQ
|
|
and makes the task IRQ available for re-allocation.
|
|
|
|
|
|
Purpose
|
|
*******
|
|
|
|
Use a task IRQ when the work required to process an interrupt
|
|
cannot be done in an ISR, either because it takes a long time
|
|
or it requires the processing routine to block.
|
|
|
|
Usage
|
|
*****
|
|
|
|
Configuring Task IRQs
|
|
=====================
|
|
|
|
Set the :option:`MAX_NUM_TASK_IRQS` configuration option
|
|
to specify the number of task IRQs allowed in the project.
|
|
|
|
The default value of zero for this option disables task IRQs.
|
|
|
|
.. note::
|
|
|
|
Task-level IRQs are microkernel objects, but are *not* configured in a
|
|
project MDEF file.
|
|
|
|
|
|
Example: Allocating a Task IRQ
|
|
==============================
|
|
|
|
This code associates a task IRQ with interrupts generated by a device.
|
|
Interrupts from that device are then enabled
|
|
so they can be processed using the task IRQ.
|
|
|
|
.. code-block:: c
|
|
|
|
#define FOO_DEVICE 2 /* device "foo" uses task IRQ object 2 */
|
|
#define FOO_IRQ 37 /* device "foo" uses IRQ 37 */
|
|
#define FOO_PRIO 3 /* device "foo" uses interrupt priority 3 */
|
|
|
|
if (task_irq_alloc(FOO_DEVICE, FOO_IRQ, FOO_PRIO) == INVALID_VECTOR) {
|
|
/* The task IRQ or the interrupt source is not available */
|
|
printf("Task IRQ allocation failed!");
|
|
}
|
|
|
|
|
|
Example: Servicing Interrupts using a Task IRQ
|
|
==============================================
|
|
|
|
This code allows a task to wait for an interrupt from a device,
|
|
acknowledge the interrupt, and take the necessary steps to service it.
|
|
|
|
.. code-block:: c
|
|
|
|
task_irq_test_wait(FOO_DEVICE);
|
|
|
|
/* Device interrupt is now masked */
|
|
/* Do pre-acknowledgement device processing (if any) */
|
|
|
|
task_irq_ack(FOO_DEVICE);
|
|
|
|
/* Device interrupt is now unmasked */
|
|
/* Do post-acknowledgement device processing (if any) */
|
|
|
|
|
|
The steps required to service a device are device-specific.
|
|
In some cases all processing may need to be completed
|
|
before the interrupt is acknowledged,
|
|
while in other cases no processing at all should be done
|
|
until the interrupt is acknowledged.
|
|
Some devices may require processing both before and after acknowledgement.
|
|
|
|
|
|
Example: Freeing a Task IRQ
|
|
===========================
|
|
|
|
This code allows a task to disassociate a task IRQ
|
|
from interrupts generated by its associated device.
|
|
Interrupts from that device are no longer enabled.
|
|
|
|
.. code-block:: c
|
|
|
|
task_irq_free(FOO_DEVICE);
|
|
|
|
|
|
|
|
APIs
|
|
****
|
|
|
|
The following task IRQ APIs are provided by :file:`microkernel.h`:
|
|
|
|
+----------------------------------------+-----------------------------------+
|
|
| Call | Description |
|
|
+========================================+===================================+
|
|
| :c:func:`task_irq_alloc()` | Binds a task IRQ to a device |
|
|
| | and enables interrupts. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_irq_ack()` | Acknowledges an interrupt and |
|
|
| | re-enables the interrupt. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_irq_free()` | Unbinds a task IRQ from a device |
|
|
| | and disables interrupts. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_irq_test()` | Tests to determine if an |
|
|
| | interrupt has occurred. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_irq_test_wait()` | Waits for an interrupt to occur. |
|
|
+----------------------------------------+-----------------------------------+
|
|
| :c:func:`task_irq_test_wait_timeout()` | Waits for an interrupt to occur |
|
|
| | within a specified time period. |
|
|
+----------------------------------------+-----------------------------------+
|