Home > Articles > Programming

  • Print
  • + Share This
This chapter is from the book

3.2 Interrupts

An interrupt is an asynchronous external event that occurs during program execution, causing a break in the normal program execution. Typically, these external events are hardware related, such as a button press or timer expiration. Interrupts can happen at any time. Interrupts allow time-critical operations to be performed with higher precedence over normal program execution.

Similar to exception processing, when an interrupt occurs, the processor jumps to a specific address for execution of the Interrupt Service Routine (ISR). Hardware support for interrupts varies among different architectures. Each processor has its own number of interrupt pins to trigger the ISR.

The methods for vector handling among different architectures are also diverse. Some processor architectures support vectoring interrupts to individual vectors, while others have a single vector for all interrupts. When individual vectors are supported, an ISR can be attached directly to the vector for processing when the interrupt occurs. For single vector support, the software must determine which interrupt occurred before proceeding to the appropriate ISR.

One of the key concerns in embedded systems with respect to interrupts is latency. Latency is the interval of time from when an interrupt occurs until the ISR begins to execute. eCos employs an interrupt handling scheme to reduce interrupt latency in the system.

3.2.1 eCos Interrupt Model

eCos uses a split interrupt handling scheme where the interrupt processing is divided into two parts. The first part is the ISR, and the second part is the Deferred Service Routine (DSR). This scheme allows for the minimal amount of interrupt latency in the system by reducing the amount of time spent inside interrupt service routines. The idea is to keep the processing done in the ISR to a bare minimum. In this scheme, the DSR is executed with interrupts enabled, allowing other higher priority interrupts to occur and be processed in the midst of servicing a lower priority interrupt.

In some cases, where very little interrupt processing needs to be done, the interrupt can be handled in the ISR completely. If more complex servicing is required, a DSR should be used. The DSR is executed at a later time when thread scheduling is allowed. Executing the DSR at a later time allows the DSR to use kernel synchronization mechanisms; for example, to signal a thread, via a semaphore, that an interrupt has occurred. However, there are periods where thread scheduling is disabled by the kernel, although these periods are kept as small as possible. User threads can suspend scheduling as well. This prevents the DSR from executing. Preventing the DSR from executing in a timely manner can lead to system failures from an interrupt source overrunning. These issues should be kept in mind when designing the interrupt structure and how it interacts with the threads in the system.

In most cases, the DSR is executed immediately after the ISR completes. However, if a thread has locked the scheduler, the DSR is delayed until the thread unlocks it. The priority scheme is that ISRs have absolute priority over DSRs, and DSRs have absolute priority over threads.

NOTE

eCos does not offer any configuration options to change the interrupt priority scheme among the ISR, DSR, and thread.

For the split interrupt handling scheme to work, the ISR must ensure the interrupt that just occurred does not recur until the DSR has finished its processing. To accomplish this, the ISR masks the current interrupt and the DSR will unmask the current interrupt after it has been serviced.

Some HAL implementations offer an interrupt nesting scheme. In this scenario, higher priority interrupts can interrupt, and be processed before, lower priority interrupts. A configuration option is available to enable this nesting functionality, as shown in Item List 3.5.

3.2.1.1 Interrupt and Scheduler Synchronization

It is important to understand the interaction between the interrupt (ISR and DSR) and the scheduler. Certain guidelines must be followed during interrupt processing to ensure proper operation.

First, ISRs cannot make any scheduler-related synchronization function calls. These include kernel API functions for semaphores, mutexes, and condition variables. Kernel synchronization functions cause interaction with the scheduler, which is disabled during ISR execution. Making such calls causes undefined behavior in the system and can lead to system failures. The eCos interrupt scheme allows these synchronization calls to be made from the DSR.

Typically, the DSR will execute immediately after the ISR finishes. DSRs are only delayed if the thread that was interrupted had locked the scheduler for some reason. Since the DSR executes when thread scheduling is enabled, certain kernel synchronization calls are allowed from within the DSR. This enables a DSR to wake up a thread for additional processing after the interrupt has occurred.

However, DSRs must not make a synchronization call that blocks. Blocking occurs when code execution must wait for a resource to be released. For example, using the kernel API call cyg_mutex_lock stops the current thread from executing until the mutex is released, with a cyg_mutex_unlock call.

NOTE

It is worth bringing additional attention to this point about calling functions within a DSR. Any function that blocks cannot be called from within the DSR. This includes C library functions, such as printf, that might use blocking calls internally.

An example of a DSR that uses one of the kernel synchronization primitives is shown in Code Listing 3.2.

3.2.2 Interrupt Configuration

The eCos interrupt configuration options affect the way interrupts are processed in the system. Configuration options for interrupts are available at the HAL and kernel level. The configuration options available are architecture dependent.

The HAL-level configuration options are located under the HAL Interrupt Handling (CYGPKG_HAL_COMMON_INTERRUPTS) within the HAL Common Configuration Components. Item List 3.4 lists the configuration options available for setting up interrupts at the HAL level.

Item List 3.4 HAL Interrupt Configuration Options

Option Name

Use Separate Stack For Interrupts

CDL Name

CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK

Description

Allows a separate stack, maintained by the HAL, during interrupt processing. This eliminates the need for every thread stack to allow space for interrupt handlers. This option is enabled by default.

Option Name

Interrupt Stack Size

CDL Name

CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE

Description

Specifies, in bytes, the stack size for the interrupt stack. This is the stack that will be used for all interrupts when Use Separate Stack For Interrupts is enabled. The value for this option is dependent on the architecture and application, as well as other interrupt configu-ration options, such as interrupt nesting. This stack is also used during the HAL startup process. The default value for this option is 4096.

Option Name

Allow Nested Interrupts

CDL Name

CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING

Description

Causes the HAL default interrupt VSR to re-enable interrupts prior to invoking the interrupt handler. This allows other interrupts, typically of higher priority, to occur and be processed. This option is disabled by default.

Option Name

Save Minimum Context On Interrupt

CDL Name

CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT

Description

Permits the HAL interrupt handling code to use architecture-specific calling conventions, reducing the amount of state information saved. This improves performance and reduces code size. The drawback is that debugging is often more difficult. This option is enabled by default.

Option Name

Chain All Interrupts Together

CDL Name

CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN

Description

Allows all interrupt vectors to be chained, requiring each handler to check if it needs to process the interrupt. The default for this option is disabled, allowing interrupts to be attached to individual vectors.

Option Name

Ignore Spurious Interrupts

CDL Name

CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS

Description

Specifies whether to ignore an interrupt that might occur from the hardware source not being properly de-bounced or interrupts coming from glitches. This option is disabled by default.


Careful consideration is necessary when specifying the HAL interrupt configuration settings. Since the DSR executes with interrupts enabled, another interrupt might occur during the execution of the DSR. This means that the processor state information, which can be sizeable for certain architectures, for the current interrupt needs to be saved on the stack.

The stack used depends on the Use Separate Stack For Interrupts option. If this option is disabled, every thread in the system needs to be able to store the interrupt state information on its stack, since interrupts can happen at any time. If multiple interrupts occur, the stack would need the resources to hold the state information for each of these interrupts.

If Use Separate Stack For Interrupts is enabled, the threads in the system would only need to store a single interrupt state from the interrupt that caused the thread to de-schedule, along with its own thread state information. Only the interrupt stack has the responsibility to store this state information. The size of the interrupt stack should be carefully selected.

Another option that can change the way interrupts are handled is the configuration of Allow Nested Interrupts. The default setting for this option is disabled, meaning that interrupts are disabled during the ISR. When this option is enabled, the ISR enables interrupts to the processing of any higher priority interrupts that might occur. Some architectures support this feature in hardware. In most systems, the need to allow nested interrupts is nonexistent because the ISR is kept very short and the main work is accomplished in the DSR.

The kernel-level interrupt configuration options are under the Kernel Interrupt Handling (CYGPKG_KERNEL_INTERRUPTS) component. Within this component is the main option Use Delayed Service Routines (CYGIMP_KERNEL_INTERRUPTS_DSRS), which enables or disables the eCos split interrupt handling scheme.

NOTE

If the Use Delayed Service Routines configuration option is disabled, it is up to the user to accommodate synchronization between ISRs and threads. Many of the kernel API functions cannot be called from an ISR context, as shown in the kernel API function tables throughout this book.

The kernel-level interrupt suboptions available when using DSRs are listed in Item List 3.5.

Item List 3.5 Kernel Interrupt Configuration Options

Option Name

Use Linked Lists For DSRs

CDL Name

CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST

Description

Allows the kernel to keep track of pending DSRs in a linked list, preventing a table over-flow from occurring. However, interrupts are disabled for a brief period while the kernel traverses the list. Alternatively, a fixed-size table can be used, with the number of entries configurable. This option is enabled by default.

Option Name

Use Fixed-Size Table For DSRs

CDL Name

CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE

Description

Enables the use of a fixed-size table for keeping track of pending DSRs in the kernel. If this option is enabled, the number of entries in the list is configurable as a suboption. This option is disabled by default.

Option Name

Chain All Interrupts Together

CDL Name

CYGIMP_KERNEL_INTERRUPTS_CHAIN

Description

Allows all interrupt vectors to be chained, requiring each handler to check if it needs to process the interrupt. The default for this option is disabled, allowing interrupts to be attached to individual vectors.


3.2.3 Interrupt Handling

An interrupt is a type of exception that can be found in a processor's exception table. As mentioned previously, different architectures support interrupts in various methods; however, eCos provides a standard method for handling interrupts across all HAL architectures. The ARM architecture is the exception that deviates from the standard eCos interrupt handling model.

The eCos interrupt handling mechanism, described in this section, can be bypassed by installing a vector service routine in the VSR table directly from the application layer. The application is then solely responsible for implementing, in assembly language, all support that would otherwise have been provided by the HAL default interrupt VSR, such as storing and restoring the processor's current state after the interrupt has been serviced.

We are going to take a look at the default configuration when the HAL default interrupt VSR is used. The HAL default interrupt VSRs for the different architectures are shown in Table 3.2. Figure 3.2 illustrates the execution flow of the eCos interrupt handling method. This figure shows the level—application, kernel, and HAL—responsible for executing each piece of code.

Table 3.2 Default Interrupt Vector Service Routines

Architecture

Default Interrupt Vector Service Routine Name

CalmRISC16a

__default_irq_vsr and __default_fiq_vsr

Fujitsu FR-V

_interrupt

i386 (including Synth), PowerPC, SuperH

cyg_hal_default_interrupt_vsr

Hitachi H8/300, MIPS, MN10300

__default_interrupt_vsr

V8x

do_interrupt

SPARC, SPARClite

hal_default_interrupt_vsr


The following is a step-by-step description of the execution flow shown in Figure 3.2; the numbers correspond to the events in the diagram.

Figure 02Figure 3.2 eCos interrupt handling execution flow.


  1. The first item in Figure 3.2 shows the execution of a thread.

  2. The next event is an external hardware interrupt.

  3. Now, the processor looks into the VSR table, hal_vsr_table, to determine the location of the interrupt vector service routine to execute. During HAL startup, hal_mon_initinstalls the default interrupt VSR into the VSR table for the external interrupt. The names of the default interrupt VSRs for the different architectures are shown in Table 3.2. The ARM architecture is not shown in the table because it defines separate vector service routines for each of its interrupts.

  4. Next, the default interrupt VSR begins executing. The first task of the default interrupt VSR is to save the current processor state. As mentioned before, the current processor's state can be saved either on a thread's stack or on the separate interrupt stack, depending on the HAL interrupt configuration options selected.

    After the processor's state information has been stored, the default interrupt VSR increments the cyg_scheduler_sched_lockkernel variable to ensure that scheduling does not take place.

    Next, the default vector service routine needs to find out what ISR to call. ISRs are installed by the application, as we see in the example in Code Listing 3.2.

    The HAL uses three tables, implemented as arrays, to maintain the ISR information needed. The size of these tables is architecture specific. The ISR tables are:

    • hal_interrupt_handlers—contains the addresses of the interrupt service routines installed by the application.

    • hal_interrupt_data—contains the data to be passed into the ISR.

    • hal_interrupt_objects—contains information that is used at the kernel level and hidden from the application layer.

    The HAL default interrupt VSR uses an architecture-specific function, hal_intc_decode, to perform the lookup into the hal_interrupt_handlers table. This function finds the index into the table based on the interrupt vector number and/or through examining the hardware, such as an interrupt controller. The value is used for indexing into the data (which is passed into the ISR) and objects (used at the kernel level) tables as well.

  5. Next, the default VSR calls the ISR installed by the application. The ISR, which executes at the application level, performs any necessary functions for the particular interrupt. The ISR notifies the kernel that the DSR should be posted for execution by returning CYG_ISR_CALL_DSR. The ISR also returns CYG_ISR_HANDLED to terminate any chained interrupt processing. An example of an application ISR and DSR is shown in Code Listing 3.2.

  6. After the ISR returns, the default interrupt VSR calls the function interrupt_end. The function interrupt_endis part of the kernel interrupt handling code and can be found in the file intr.cxxunder the kernel\current\src\intrsubdirectory.

  7. If a DSR needs to execute, interrupt_end calls the function post_dsr. post_dsr, also part of the kernel interrupt handling code in the file intr.cxx, manages the implementation of posting the DSR. The two kernel interrupt configura-tion options Use Linked Lists For DSRs and Use Fixed-Size Table For DSRs determine the structure for the DSR list. See the Interrupt Configuration section in this chapter for a detailed description of these options.

  8. After post_dsrreturns, interrupt_endthen unlocks the scheduler.

  9. If the scheduler lock variable is at 0, the DSR executes. If the scheduler lock variable is greater than 0, then the thread that locked the scheduler executes at this point. In our case, we assume another thread has not locked the scheduler. An example of a DSR is shown in Code Listing 3.2. After the DSR completes, the scheduler unlock code continues execution.

  10. Next, the HAL default interrupt VSR restores the processor state. This takes place in the routine restore_state, the same function called from the default exception VSR.

  11. Finally, thread execution continues.

NOTE

It is important to realize that the thread interrupted, as described in step 1, might not be the thread that is restored for execution by the scheduler, detailed in step 11. This can happen if the DSR executes, as described in step 8, and causes another thread to become ready to run that is at a higher priority than the thread that was interrupted.

For example, let's say that two threads are created in a system—thread A and thread B—where thread B is at a higher priority than thread A. Thread B waits on a semaphore indicating that data has arrived from a device. Now suppose that thread A is currently executing when the device causes an interrupt, indicating data has arrived, as shown in step 2. Steps 3 through 8 occur as described. However, in step 9, the DSR associated with this interrupt posts the semaphore that thread B is waiting on. When the scheduler unlock code continues execution, the context of thread B is restored because it is at a higher priority than thread A. Therefore, in step 11, thread B executes.

Let's now look at ISR and DSR functions. Both the ISR and DSR are set up in the application using the kernel API function calls. Code Listing 3.2 shows an example of ISR and DSR functions and how the kernel API is used to set them up.

 1  #include <cyg/kernel/kapi.h> 2
 2
 3  static cyg_interrupt int1;
 4  static cyg_handle_t int1_handle;
 5  static cyg_sem_t data_ready;
 6
 7  #define CYGNUM_HAL_INTERRUPT_1 1
 8  #define CYGNUM_HAL_PRI_HIGH 0
 9
10  //
11  // Interrupt service routine for interrupt 1.
12  //
13  cyg_uint32 interrupt_1_isr(
14              cyg_vector_t vector,
15              cyg_addrword_t data)
16  { 
17    // Block this interrupt from occurring until
18    // the DSR completes.
19    cyg_interrupt_mask( vector );
20
21    // Tell the processor that we have received
22    // the interrupt.
23    cyg_interrupt_acknowledge( vector );
24
25    // Tell the kernel that chained interrupt processing
26    // is done and the DSR needs to be executed next.
27    return( CYG_ISR_HANDLED | CYG_ISR_CALL_DSR );
28  }
29
30  // 
31  // Deferred service routine for interrupt 1.
32  // 
33  void interrupt_1_dsr(
34         cyg_vector_t vector,
35         cyg_ucount32 count,
36         cyg_addrword_t data)
37  {
38    // Signal the thread to run for further processing.
39    cyg_semaphore_post( &data_ready );
40
41    // Allow this interrupt to occur again.
42  cyg_interrupt_unmask( vector );
43  }
44
45  //
46  // Main starting point for the application.
47  //
48  void cyg_user_start(
49         void)
50  {
51    cyg_vector_t int1_vector = CYGNUM_HAL_INTERRUPT_1;
52    cyg_priority_t int1_priority = CYGNUM_HAL_PRI_HIGH;
53
54    // Initialize the semaphore used for interrupt 1.
55    cyg_semaphore_init( &data_ready, 0 );
56
57    //
58    // Create interrupt 1.
59    //
60    cyg_interrupt_create(
61       int1_vector,
62       int1_priority,
63       0,
64       &interrupt_1_isr,
65       &interrupt_1_dsr,
66       &int1_handle,
67       &int1);
68
69    // Attach the interrupt created to the vector.
70    cyg_interrupt_attach( int1_handle );
71
72    // Unmask the interrupt we just configured.
73    cyg_interrupt_unmask( int1_vector );
74  }

Code Listing 3.2 Example using the eCos kernel APIs for installing an interrupt within an application.

As we see in Code Listing 3.2, the main function, cyg_user_start on line 48, is called during the kernel startup procedure. We go through the kernel startup procedure in Chapter 5. After initializing the semaphore, see line 55, which is used in the DSR, the interrupt is created for the interrupt vector CYGNUM_HAL_INTERRUPT_1, using the kernel function cyg_interrupt_create, on line 60. The interrupt vector (CYGNUM_HAL_INTERRUPT_1 on line 51) and priority (CYGNUM_HAL_PRI_HIGH on line 52) are defined on lines 7 and 8, respectively. The data field, as we see on line 63, is set to zero since we do not need to pass anything into the ISR or DSR.

Next, the main function handles attaching the interrupt just created to the vector using cyg_interrupt_attach, shown on line 70. Finally, the interrupt 1 vector is unmasked, by cyg_interrupt_unmask on line 73, so that it can be processed when global interrupts are enabled. Global interrupts are enabled manually or, as in this example, when the scheduler starts after cyg_user_start returns.

The ISR, interrupt_1_isr on line 13, masks the current interrupt vector, shown on line 16, to ensure that it does not occur before the DSR has finished. It then acknowledges the interrupt within the processor, as we see on line 23. Lastly, the ISR signals to the kernel to post the DSR for further processing by returning CYG_ISR_CALL_DSR, on line 27. The ISR also returns CYG_ISR_HANDLED to terminate any chained interrupt processing.

When the DSR executes, interrupt_1_dsr on line 33, it signals a semaphore, as we see on line 39, and then unmasks the current interrupt, shown on line 42, so it can occur again. The semaphore, data_ready, used in this example demonstrates a method of synchronization between an interrupt and a thread. The thread, which is not included in the code listing, waits on this semaphore before beginning its processing. You can find the kernel API function descriptions for semaphores, including an example using the semaphore kernel API, in Chapter 6, Threads and Synchronization Mechanisms.

Detailed descriptions of the kernel API functions used in Code Listing 3.2, and the underlying HAL macros, are found in this chapter in the Interrupt Control section.

NOTE

In some circumstances it might be more useful to explicitly post a DSR, or multiple DSRs, instead of using the CYG_ISR_CALL_DSR return value from the ISR. An ISR can explicitly post a DSR by calling cyg_interrupt_post_dsr and passing in the interrupt object returned from the cyg_interrupt_create function call, intr. This allows a single ISR to trigger multiple DSRs, or for an ISR to determine, at the time of the interrupt, which specific DSR to run from a list of possible DSRs.

The function cyg_interrupt_post_dsr is not part of the published kernel interrupt API. The function is implemented in the file intr.cxx in the intr subdirectory under the kernel source code directory. To use this function, it must be declared as follows:

extern void
 cyg_interrupt_post_dsr(CYG_ADDRWORD
intr_handle); 

Attaching different DSRs to a single interrupt is accomplished by creating multiple interrupt objects that have the same ISR with a different DSR. In the call to the function cyg_interrupt_create, different interrupt objects are passed in the intr parameter along with different DSRs in the dsr parameter. However, the same ISR is passed in the isr parameter. It is important to understand that the function cyg_interrupt_attach only needs to be called once, with one of the interrupt handles created for the ISR. See Item List 3.7 for details about the kernel API for interrupts.

3.2.4 Interrupt Control

The HAL and kernel offer control over interrupt configuration. The HAL controls interrupts through the use of macros. The macro names are common across all HAL architectures; however, the implementations of these macros are architecture specific. The HAL macros are defined in the file hal_intr.h under the arch subdirectory.

The kernel API contains interrupt control functions that make use of these macros. Therefore, it is not necessary for an application to call directly into the HAL; rather, it can use the kernel API to configure system interrupts. The HAL and kernel interrupt control functionality is broken down into three groups:

  • Interrupt Service Routine Management

  • Interrupt State Management

  • Interrupt Controller Management

NOTE

It is important to use the kernel API functions and avoid using the HAL macros directly. Using the kernel API guarantees consistency over the underlying HAL macro implementations. An example of maintaining consistency is when using the configuration option to chain interrupts together. By going through the kernel API when attaching interrupts (cyg_interrupt_attach), rather than directly using the HAL_INTERRUPT_ATTACH macro, the algorithm for inserting the interrupt in the chain list is handled by the kernel API function. This ensures that the interrupts are inserted into the list using the process each time.

3.2.4.1 Interrupt Service Routine Management

The first of the three groups, Interrupt Service Routine Management, controls the attachment and detachment of interrupt service routines within the three HAL ISR tables (handlers, data, and objects). The HAL ISR Management macros are described in Item List 3.6.

Item List 3.6 HAL Interrupt Service Routine Management Macros

Syntax:

HAL_INTERRUPT_ATTACH(
 _vector_,
 isr_,
 data_,
 object_
 )

Parameters:

_vector_—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts. This value is used to determine the index into the ISR tables.

 

isr_—ISR address to install into the handler table.

 

data_—data address to install into the data table.

 

object_—object address to install into the object table.

Description:

Places the parameters into the ISR tables for the given interrupt vector. The ISR is called from the HAL default VSR when the interrupt occurs, the data and object are passed into the ISR as parameters.

Syntax:

HAL_INTERRUPT_DETACH(_
 vector_,
 _isr_
 );

Parameters:

_vector_—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts. This value is used to determine the index into the ISR tables.

 

_isr_—ISR address to remove from the handler table.

Description:

Remove the interrupt service routine from the ISR table. The ISR is then set to a HAL default ISR. The data and object tables are set to zero for this vector index.


The kernel API functions for Interrupt Service Routine Management are listed in Item List 3.7

Item List 3.7 Kernel Interrupt Service Routine Management API Functions

Syntax:

void
cyg_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
 );

Context:

Thread

Parameters:

vector—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts. priority—for certain HAL architectures, an interrupt priority level is supported. This value is used when the interrupt is attached. data—data address to install into the data table when the interrupt is attached. Often, this parameter is used to provide context information when an ISR is attached to multiple interrupt sources. For example, the parameter can be a pointer to a structure containing state information for the interrupt source identifying which interrupt triggered.

isr—address of the interrupt service routine to install when the interrupt is attached.

dsr—address of the deferred service routine to install.

handle—pointer to the new interrupt.

intr—returned address of the new interrupt object.

Description:

Construct an interrupt object in memory. The interrupt is not attached to the vector, however, until cyg_interrupt_attach is called.

Syntax:

void
cyg_interrupt_delete(
 cyg_handle_t interrupt
 ); 

Context:

Thread

Parameters:

interrupt—handle to the interrupt.

Description:

Remove the interrupt object from memory, freeing the memory passed in the intr parameter to cyg_interrupt_create. This call also detaches, using the HAL_INTERRUPT_DETACH macro, the ISR, data, and object from the ISR tables.

Syntax:

void
cyg_interrupt_attach(
 cyg_handle_t interrupt
 );

Context:

Thread

Parameters:

interrupt—handle to the interrupt.

Description:

Attach the interrupt to the vector allowing interrupts to be delivered to the ISR. This function makes use of the HAL_INTERRUPT_SET_LEVEL and HAL_INTERRUPT_ATTACH macros. The interrupt is also set up in the chain list if the configuration option is enabled.

Syntax:

void
cyg_interrupt_detach(
 cyg_handle_t interrupt
 ); 

Context:

Thread

Parameters:

interrupt—handle to the interrupt.

Description:

Detach the interrupt from the vector preventing interrupts from being delivered to the ISR. This function calls the HAL_INTERRUPT_DETACH macro and removes the interrupt from the chain list if the configuration option is enabled.


3.2.4.2 Interrupt State Management

The second group, Interrupt State Management, allows control over the state of the processor's interrupt mask mechanism by accessing the global interrupt enable found in the processor's register. These functions do not access the interrupt controller, which might be present on certain variants. The HAL Interrupt State Management macros are described in Item List 3.8.

Item List 3.8 HAL Interrupt State Management Macros

Syntax:

HAL_DISABLE_INTERRUPTS(
       _old_
       ) 

Parameters:

_old_—returned state of the interrupt mask.

Description:

Disable all interrupts. This is accomplished by using the interrupt enable found in one of the processor's registers.

Syntax:

HAL_ENABLE_INTERRUPTS(
        ) 

Description:

Enable all interrupts. This is accomplished by using the interrupt enable found in one of the processor's registers.

Syntax:

HAL_RESTORE_INTERRUPTS(
       _old_
       ) 

Parameters:

_old_—state of the interrupt mask.

Description:

Restore the interrupts according to the state of the interrupt mask specified.

Syntax:

HAL_QUERY_INTERRUPTS(
       _old_
       ) 

Parameters:

_old_—returned state of the interrupt mask.

Description:

Determine state of interrupt mask and return the value.


The kernel API functions for Interrupt State Management are listed in Item List 3.9.

Item List 3.9 Kernel Interrupt State Management API Functions

Syntax:

void
cyg_interrupt_disable(
 void
 ); 

Context:

Any

Parameters:

None

Description:

Disable all interrupts, using the HAL_INTERRUPT_DISABLE macro.

Syntax:

void
cyg_interrupt_enable(
 void
 );

Context:

Any Parameters: None

Description:

Enable all interrupts, using the HAL_INTERRUPT_ENABLE macro.


3.2.4.3 Interrupt Controller Management

The final group, Interrupt Controller Management, provides control over any interrupt controller that might be present for a specific variant. Not all HAL architectures have an interrupt controller.

A specific platform or variant that does contain an interrupt controller provides the implementation of these macros in its own interrupt definition file. The names of the platform or variant files containing these override macros differ among architectures. The HAL Interrupt Controller Management macros are defined in Item List 3.10.

Item List 3.10 HAL Interrupt Controller Management Macros

Syntax:

HAL_INTERRUPT_MASK(
 _vector_
 ) 

Parameters:

_vector_—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

Description:

Block the designated interrupt from occurring. This is typically a platform or variant specific implementation, which requires masking interrupts in the processor's registers.

Syntax:

HAL_INTERRUPT_UNMASK(
 _vector_
 ) 

Parameters:

_vector_—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

Description:

Unblock the designated interrupt. This is typically a platform- or variant-specific implementation, which requires masking interrupts in the processor's registers.

Syntax:

HAL_INTERRUPT_ACKNOWLEDGE(
 _vector_
 ) 

Parameters:

_vector_—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

Description:

Acknowledges the current interrupt from the specified vector. This informs the processor that the interrupt was received and resets the interrupt to an inactive state. This is typically a platform- or variant-specific implementation, where the HAL modifies the processor's interrupt acknowledge bit in a register.

Syntax:

HAL_INTERRUPT_CONFIGURE(
 _vector_,
 level_,
 up_
 )

 

_vector_—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

 

_level_—specifies whether the interrupt is level- or edge-triggered.

 

_up_—specifies a falling or rising edge for edge-triggered interrupts and a high or low

Parameters:

level for level-triggered interrupts.

Description:

Programs the interrupt controller with the configuration settings for a specified interrupt. These settings determine the method for detecting an interrupt. Not all HAL architectures support these configuration settings.

Syntax:

HAL_INTERRUPT_SET_LEVEL(
 _vector_,
 _level_
 )

Parameters:

_vector_—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

 

_level_—priority level setting for the specified interrupt.

Description:

Configures the priority level of the specified interrupt. Not all HAL architectures support these configuration settings.


The kernel API functions for the Interrupt Controller Management group are defined in Item List 3.11.

Item List 3.11 Kernel Interrupt Controller Management API Functions

Syntax:

void
cyg_interrupt_mask(
 cyg_vector_t vector
 );

Context:

Any

Parameters:

vector—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

Description:

Program the interrupt controller to block delivery of interrupts for the vector specified. This function calls the HAL_INTERRUPT_MASK macro. All interrupts are disabled during this function call.

Syntax:

void cyg_interrupt_mask_intunsafe(
 cyg_vector_t vector
 ); 

Context:

Any

Parameters:

vector—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

Description:

Program the interrupt controller to block delivery of interrupts for the vector specified. This function can be called when interrupts are currently disabled.

Syntax:

void
cyg_interrupt_unmask(
 cyg_vector_t vector
 ); 

Context:

Any

Parameters:

vector—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

Description:

Program the interrupt controller to unblock interrupts for the specified vector, allowing interrupts to be delivered to the ISR. This function calls the HAL_INTERRUPT_UNMASK macro. All interrupts are disabled during this function call.

Syntax:

void
cyg_interrupt_unmask_intunsafe(
 cyg_vector_t vector
 ); 

Context:

Any

Parameters:

vector—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

Description:

Program the interrupt controller to unblock interrupts for the specified vector, allowing interrupts to be delivered to the ISR. This function can be called when interrupts are currently disabled.

Syntax:

void
cyg_interrupt_acknowledge(
 cyg_vector_t vector
 ); 

Context:

Any

Parameters:

vector—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts.

Description:

Acknowledge the current interrupt from the specified vector. This function is called from within the ISR to cancel the interrupt request from the processor, preventing a re-trigger of the same interrupt. This function calls the HAL_INTERRUPT_ACKNOWLEDGE macro.

Syntax:

void
cyg_interrupt_configure(
 cyg_vector_t vector,
 cyg_bool_t level,
 cyg_bool_t up
 ); 

Context:

Any

Parameters:

vector—HAL architecture-specific interrupt definition number. Each HAL defines, in the file hal_intr.h, all interrupts supported starting from 0. The platform or variant can define additional interrupts. level—specifies whether the interrupt is level or edge triggered. up—specifies a falling or rising edge for edge-triggered interrupts, and a high or low level for level-triggered interrupts.

Description:

Program the interrupt controller with the method for detecting an interrupt. This function calls the HAL_INTERRUPT_CONFIGURE macro.


The kernel API functions for Symmetric Multi-Processing (SMP) systems are defined in Item List 3.12. eCos support for SMP is covered in Chapter 8.

Item List 3.12 Kernel SMP Interrupt API Functions

Syntax:

void cyg_interrupt_set_cpu(
      cyg_vector_t vector, cyg_cpu_t cpu ); 

Context:

Any

Parameters:

vector—exception vector to retrieve from the VSR table. Each HAL defines, in the file hal_intr.h, all exceptions supported starting from 0. This value is used to determine the index into the VSR table. cpu—processor to receive interrupt.

Description:

Specifies the processor to handle the hardware interrupt. The VSR, ISR, and possibly DSR execute on this processor as well.

Syntax:

cyg_cpu_t cyg_interrupt_get_cpu(
      cyg_vector_t vector ); 

Context:

Any

Parameters:

vector—exception vector to set in the VSR table. Each HAL defines, in the file hal_intr.h, all exceptions supported starting from 0. This value is used to determine the index into the VSR table.

Description:

Returns the CPU designated to handle the specified interrupt.


  • + Share This
  • 🔖 Save To Your Account