diff -r 4816d766a08a -r f345bda72bc4 Symbian3/PDK/Source/GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita --- a/Symbian3/PDK/Source/GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita Tue Mar 30 11:42:04 2010 +0100 +++ b/Symbian3/PDK/Source/GUID-76A30EC4-4B99-5471-9E80-F853C91485BC.dita Tue Mar 30 11:56:28 2010 +0100 @@ -1,192 +1,194 @@ - - - - - -Interrupt -DispatcherAn interrupt is a condition that causes the CPU to suspend normal -execution, enter interrupt handling state and jump to a section of code called -an interrupt handler. The ASSP/variant part of the base port must implement -an interrupt dispatcher to manage interrupts. -

An interrupt source is a hardware device or software action that can force -the CPU to enter interrupt handling state.

-

Typically, a number of interrupt sources are monitored by an interrupt -controller. This is hardware that generates a single interrupt notification -to the CPU, and provides information about which interrupts are pending, i.e. -which interrupts require action to be taken.

-
ISR

An -interrupt service routine, or ISR, is code that deals with a pending interrupt. -The Symbian platform kernel responds to an interrupt notification by calling -an ISR for each pending interrupt. The process of calling ISRs is called interrupt -dispatch.

The ISR is a single bare function. It is not a class member.

Each -ISR takes a single 32-bit parameter that is, typically, a pointer to an owning -class, although it can be any value that is appropriate. The parameter is -defined as a TAny * type, so a cast is almost always necessary.

ISRs -are usually kept in an ISR table.

-
Interrupt ID

An -interrupt source is identified by number, defined as a TInt type. -Typically, the ASSP layer defines this number for each interrupt in a header -file and exports it so that it can be included and used by device drivers.

Where -the ASSP layer is split into a common layer and a variant (device specific) -layer, then the variant layer may also define its own set of interrupt IDs.

This -number is usually referred to as the interrupt ID.

-
Binding and -unbinding

Only one ISR can be associated with each possible interrupt -source. Making this association is known as binding. ISRs can be bound and -unbound during normal operation, but only one ISR can be bound to an interrupt -source at any one time.

A device driver binds an ISR by calling Interrupt::Bind(), -passing the interrupt source ID; similarly, the device driver can unbind the -ISR by calling Interrupt::Unbind(), also passing the interrupt -ID.

-
Dispatching interrupts

At its simplest, this is -the process of deciding which interrupts are pending and calling the ISR for -each.

The following pseudo code shows the general principle:

- { - FOREVER - { - Get next pending interrupt; - if None - { - return; - } - call ISR for the pending interrupt; - } - } -

In practice the dispatcher may have to do some more work to -communicate with the interrupt controller hardware.

-
Chained interrupts

A -system may have multiple interrupt controllers to handle a large number of -interrupt sources. These are usually prioritised by connecting the interrupt -output of a lower-priority controller to an interrupt input of a higher-priority -controller. This is called chaining.

- -

An interrupt from a lower priority controller will appear as an -interrupt on the highest-priority controller.

When the interrupt dispatcher -of the higher-priority controller detects that it is the chained interrupt -that is pending, the usual way of dealing with this is to run a secondary -dispatcher to determine which interrupt on the chained controller is pending.

There -may be further levels of chaining before the true source of the interrupt -has been identified.

-
Multiple interrupt -sources and pseudo interrupt sources

It is possible that a single -input to an interrupt controller is shared by several interrupt sources.

- -

It appears necessary to bind multiple ISRs to the same interrupt. -However, this is not possible. There are two ways of dealing with this:

    -
  • Maintain a list of all -ISRs that are bound to this single interrupt source, and call all the ISRs -in the list when the interrupt is dispatched. This is most conveniently implemented -by binding a single ISR to the interrupt, which then calls all the real ISRs -bound to this interrupt

  • -
  • Create pseudo interrupts. -These are extra interrupt IDs that do not exist in the interrupt controller, -but represent each of the interrupt sources connected to the single shared -interrupt source. An ISR can then be bound to each pseudo interrupt. The interrupt -dispatcher can then determine which of the sources are actually signalling -and call the appropriate ISR via that pseudo interrupt ID. This is effectively -an implementation of a chained -interrupt, and assumes that the interrupt dispatcher can identify which -of the sources is signalling.

  • -
-
Interrupts -in the split ASSP/Variant Configuration

When a common ASSP extension -is used, a device may have additional peripherals external to the ASSP, and -there needs to be a way of allowing extra interrupt binding and dispatch functions -to be added later by the variant layer. This must be handled by the port as -Symbian OS does not provide any additional API to support this.

Device -drivers should be able to use the Interrupt class functions -without having to know where the interrupt is actually implemented. This implies -that all requests should go to the core implementation of functions like Interrupt::Bind(), Interrupt::Enable() etc.

To enable the core implementation of these functions to decide -whether an interrupt ID refers to a core interrupt or device specific interrupt, -a common technique is to "tag" the interrupt ID. A simple way is to use positive -numbers to identify core interrupts and negative numbers to identify device -specific interrupts. The ISRs for device specific interrupts are not stored -in the core ISR table, instead the device specific layer provides its own -ISR table.

The general pattern for creating the core-device specific -split is that the core derives an implementation from class Asic, -and the device specific part further derives from this core implementation. -The usual technique is to add a set of virtual functions to the core class -that can be derived by the device specific part. The core can provide default -implementations for these functions that would just return KErrArgument to -trap illegal ID numbers. This API would need functions equivalent to each -of the functions defined by the Interrupt class.

As -an example, the core layer for the template reference board defines a class TemplateAssp that -is derived from Asic. TemplateAssp defines -the pure virtual functions: InterruptBind(), InterruptUnbind(), InterruptEnable() etc, -all with signatures that are the same for the comparable functions defined -by Interrupt, and which are implemented by the Template class.

- -
-
Spurious interrupts

In -the Kernel Architecture 2, it is a convention that unbound interrupts should -be bound to a "spurious" interrupt handler, i.e. an interrupt handler that -faults the system indicating the number of the interrupt. This aids debugging -by identifying interrupts that are enabled without corresponding ISRs.

-
Interrupt priority

The interrupt architecture supports -the concept of adjustable interrupt priorities. Symbian platform defines the Interrupt::SetPriority() function -that can implement this. The function is passed the ID of the interrupt source -to be adjusted together with a priority value. The meaning of the priority -value is hardware and implementation dependent, and is defined by the port.

-
The ISR table

The -Variant must provide a table where each entry defines which ISR is bound to which interrupt source. The table must have enough -space for entries for each interrupt source that is known to the Variant.

When -the Variant is split into an ASSP layer and a Variant layer, the ISR table -is put in the ASSP layer and will not normally include ISRs for the Variant -interrupt sources - these will be handled by separate chained dispatchers -in the Variant layer.

Symbian platform provides the SInterruptHandler structure, -defined in the header file ...\e32\include\kernel\arm\assp.h to -encapsulate the entry for an ISR. The ISR table is, therefore, just an array -of SInterruptHandler items. For example, if a system has -32 possible interrupt sources, then the ISR table would be defined as:

... -const TInt KInterruptSourceCount = 32; -SInterruptHandler IsrHandlers[KInterruptSourceCount]; -...

Interrupts are identified in the system by their interrupt -ID number, which is used to index into the ISR table. You are free to allocate -these numbers any way that is convenient for you.

On the template -reference board, for example, the ISR table is defined as a static data member -of the VariantASSPInterrupt class, which is derived from TemplateInterrupt. -The class is defined in ...\template_assp\template_assp_priv.h.

class TemplateInterrupt : public Interrupt - { - ... // functions -public: - static SInterruptHandler Handlers[KNumTemplateInts]; - ... - };

where KNumTemplateInts is defined in the same header -file.

Factors -that decide the size of the ISR table

The number of entries to -be reserved in the ISR table depends on the following factors:

    -
  • Where the ASSP is targeted -at only a single device, the number of possible interrupts is usually known, -and the table can include an entry for each one.

  • -
  • If any pseudo sources exist, they should be included in the main table for -efficiency, but note that this is not strictly necessary.

  • -

Other -factors affecting the ISR table

IRQs and FIQs may need to be distinguished, -although the exact requirement is hardware dependent. Although the table has -one entry for each possible interrupt source, a possible scheme may be to -group IRQs at the start of the table, and FIQs at the end of the table. If -the hardware has separate interrupt controller hardware for IRQs and FIQs -(or at least, different registers) then you will need to arrange the table -so that you can determine from the interrupt -ID whether the interrupt is an IRQ or FIQ.

For example:

- -
-
Location of interrupt handling code

Most of the -interrupt dispatching code is implemented in the ASSP layer. This includes -a list of ISRs, code for adding and removing ISRs, enabling and disabling -interrupt sources, and dispatching ISRs. The kernel only provides a pre-amble -and post-amble.

The kernel defines, but does not implement, a class -called Interrupt that exports interrupt functionality to -device drivers and other kernel code. The class provides the public API for -using interrupts (but not for dispatching them). The port must provide an -implementation for each function defined by the class.

The class is -defined in the header files ...\e32\include\kernel\arm\assp.h, -which is exported to ...\epoc32\include\kernel\arm.

See -Symbian OS Internals Book, Chapter 6 - Interrupts and Exceptions

+ + + + + +Interrupt +DispatcherAn interrupt is a condition that causes the CPU to suspend normal +execution, enter interrupt handling state and jump to a section of code called +an interrupt handler. The ASSP/variant part of the base port must implement +an interrupt dispatcher to manage interrupts. +

An interrupt source is a hardware device or software action that can force +the CPU to enter interrupt handling state.

+

Typically, a number of interrupt sources are monitored by an interrupt +controller. This is hardware that generates a single interrupt notification +to the CPU, and provides information about which interrupts are pending, i.e. +which interrupts require action to be taken.

+
ISR

An +interrupt service routine, or ISR, is code that deals with a pending interrupt. +The Symbian platform kernel responds to an interrupt notification by calling +an ISR for each pending interrupt. The process of calling ISRs is called interrupt +dispatch.

The ISR is a single bare function. It is not a class member.

Each +ISR takes a single 32-bit parameter that is, typically, a pointer to an owning +class, although it can be any value that is appropriate. The parameter is +defined as a TAny * type, so a cast is almost always necessary.

ISRs +are usually kept in an ISR table.

+
Interrupt ID

An +interrupt source is identified by number, defined as a TInt type. +Typically, the ASSP layer defines this number for each interrupt in a header +file and exports it so that it can be included and used by device drivers.

Where +the ASSP layer is split into a common layer and a variant (device specific) +layer, then the variant layer may also define its own set of interrupt IDs.

This +number is usually referred to as the interrupt ID.

+
Binding and +unbinding

Only one ISR can be associated with each possible interrupt +source. Making this association is known as binding. ISRs can be bound and +unbound during normal operation, but only one ISR can be bound to an interrupt +source at any one time.

A device driver binds an ISR by calling Interrupt::Bind(), +passing the interrupt source ID; similarly, the device driver can unbind the +ISR by calling Interrupt::Unbind(), also passing the interrupt +ID.

+
Dispatching +interrupts

At its simplest, this is the process of deciding which +interrupts are pending and calling the ISR for each.

The following +pseudo code shows the general principle:

+ { + FOREVER + { + Get next pending interrupt; + if None + { + return; + } + call ISR for the pending interrupt; + } + } +

In practice the dispatcher may have to do some more work to +communicate with the interrupt controller hardware.

+
Chained interrupts

A +system may have multiple interrupt controllers to handle a large number of +interrupt sources. These are usually prioritised by connecting the interrupt +output of a lower-priority controller to an interrupt input of a higher-priority +controller. This is called chaining.

+ +

An interrupt from a lower priority controller will appear as an +interrupt on the highest-priority controller.

When the interrupt dispatcher +of the higher-priority controller detects that it is the chained interrupt +that is pending, the usual way of dealing with this is to run a secondary +dispatcher to determine which interrupt on the chained controller is pending.

There +may be further levels of chaining before the true source of the interrupt +has been identified.

+
Multiple interrupt +sources and pseudo interrupt sources

It is possible that a single +input to an interrupt controller is shared by several interrupt sources.

+ +

It appears necessary to bind multiple ISRs to the same interrupt. +However, this is not possible. There are two ways of dealing with this:

    +
  • Maintain a list of all +ISRs that are bound to this single interrupt source, and call all the ISRs +in the list when the interrupt is dispatched. This is most conveniently implemented +by binding a single ISR to the interrupt, which then calls all the real ISRs +bound to this interrupt

  • +
  • Create pseudo interrupts. +These are extra interrupt IDs that do not exist in the interrupt controller, +but represent each of the interrupt sources connected to the single shared +interrupt source. An ISR can then be bound to each pseudo interrupt. The interrupt +dispatcher can then determine which of the sources are actually signalling +and call the appropriate ISR via that pseudo interrupt ID. This is effectively +an implementation of a chained +interrupt, and assumes that the interrupt dispatcher can identify which +of the sources is signalling.

  • +
+
Interrupts +in the split ASSP/Variant Configuration

When a common ASSP extension +is used, a device may have additional peripherals external to the ASSP, and +there needs to be a way of allowing extra interrupt binding and dispatch functions +to be added later by the variant layer. This must be handled by the port as +Symbian platform does not provide any additional API to support this.

Device +drivers should be able to use the Interrupt class functions +without having to know where the interrupt is actually implemented. This implies +that all requests should go to the core implementation of functions like Interrupt::Bind(), Interrupt::Enable() etc.

To enable the core implementation of these functions to decide +whether an interrupt ID refers to a core interrupt or device specific interrupt, +a common technique is to "tag" the interrupt ID. A simple way is to use positive +numbers to identify core interrupts and negative numbers to identify device +specific interrupts. The ISRs for device specific interrupts are not stored +in the core ISR table, instead the device specific layer provides its own +ISR table.

The general pattern for creating the core-device specific +split is that the core derives an implementation from class Asic, +and the device specific part further derives from this core implementation. +The usual technique is to add a set of virtual functions to the core class +that can be derived by the device specific part. The core can provide default +implementations for these functions that would just return KErrArgument to +trap illegal ID numbers. This API would need functions equivalent to each +of the functions defined by the Interrupt class.

As +an example, the core layer for the template reference board defines a class TemplateAssp that +is derived from Asic. TemplateAssp defines +the pure virtual functions: InterruptBind(), InterruptUnbind(), InterruptEnable() etc, +all with signatures that are the same for the comparable functions defined +by Interrupt, and which are implemented by the Template class.

+ +
+
Spurious interrupts

In +the Kernel Architecture 2, it is a convention that unbound interrupts should +be bound to a "spurious" interrupt handler, i.e. an interrupt handler that +faults the system indicating the number of the interrupt. This aids debugging +by identifying interrupts that are enabled without corresponding ISRs.

+
Interrupt priority

The +interrupt architecture supports the concept of adjustable interrupt priorities. +Symbian platform defines the Interrupt::SetPriority() function +that can implement this. The function is passed the ID of the interrupt source +to be adjusted together with a priority value. The meaning of the priority +value is hardware and implementation dependent, and is defined by the port.

+
The ISR table

The +Variant must provide a table where each entry defines which ISR is bound to which interrupt source. The table must have enough +space for entries for each interrupt source that is known to the Variant.

When +the Variant is split into an ASSP layer and a Variant layer, the ISR table +is put in the ASSP layer and will not normally include ISRs for the Variant +interrupt sources - these will be handled by separate chained dispatchers +in the Variant layer.

Symbian platform provides the SInterruptHandler structure, +defined in the header file ...\e32\include\kernel\arm\assp.h to +encapsulate the entry for an ISR. The ISR table is, therefore, just an array +of SInterruptHandler items. For example, if a system has +32 possible interrupt sources, then the ISR table would be defined as:

... +const TInt KInterruptSourceCount = 32; +SInterruptHandler IsrHandlers[KInterruptSourceCount]; +...

Interrupts are identified in the system by their interrupt +ID number, which is used to index into the ISR table. You are free to allocate +these numbers any way that is convenient for you.

On the template +reference board, for example, the ISR table is defined as a static data member +of the VariantASSPInterrupt class, which is derived from TemplateInterrupt. +The class is defined in ...\template_assp\template_assp_priv.h.

class TemplateInterrupt : public Interrupt + { + ... // functions +public: + static SInterruptHandler Handlers[KNumTemplateInts]; + ... + };

where KNumTemplateInts is defined in the same header +file.

Factors +that decide the size of the ISR table

The number of entries to +be reserved in the ISR table depends on the following factors:

    +
  • Where the ASSP is targeted +at only a single device, the number of possible interrupts is usually known, +and the table can include an entry for each one.

  • +
  • If any pseudo sources exist, they should be included in the main table for +efficiency, but note that this is not strictly necessary.

  • +

Other +factors affecting the ISR table

IRQs and FIQs may need to be distinguished, +although the exact requirement is hardware dependent. Although the table has +one entry for each possible interrupt source, a possible scheme may be to +group IRQs at the start of the table, and FIQs at the end of the table. If +the hardware has separate interrupt controller hardware for IRQs and FIQs +(or at least, different registers) then you will need to arrange the table +so that you can determine from the interrupt +ID whether the interrupt is an IRQ or FIQ.

For example:

+ +
+
Location of +interrupt handling code

Most of the interrupt dispatching code +is implemented in the ASSP layer. This includes a list of ISRs, code for adding +and removing ISRs, enabling and disabling interrupt sources, and dispatching +ISRs. The kernel only provides a pre-amble and post-amble.

The kernel +defines, but does not implement, a class called Interrupt that +exports interrupt functionality to device drivers and other kernel code. The +class provides the public API for using interrupts (but not for dispatching +them). The port must provide an implementation for each function defined by +the class.

The class is defined in the header files ...\e32\include\kernel\arm\assp.h, +which is exported to ...\epoc32\include\kernel\arm.

See +Symbian OS Internals Book, Chapter 6 - Interrupts and Exceptions

\ No newline at end of file