eCos Reference Manual
Prev | Chapter 9. HAL Interfaces | Next

# Interrupt Handling

These interfaces contain definitions related to interrupt handling. They include definitions of exception and interrupt numbers, interrupt enabling and masking, and realtime clock operations.

These definitions are normally found in `cyg/hal/hal_intr.h`. This file is supplied by the architecture HAL. Any variant or platform specific definitions will be found in `cyg/hal/var_intr.h`, `cyg/hal/plf_intr.h` or `cyg/hal/hal_platform_ints.h` in the variant or platform HAL, depending on the exact target. These files are include automatically by this header, so need not be included explicitly.

## Vector numbers

    CYGNUM_HAL_VECTOR_XXXX
    CYGNUM_HAL_VSR_MIN
    CYGNUM_HAL_VSR_MAX
    CYGNUM_HAL_VSR_COUNT

    CYGNUM_HAL_INTERRUPT_XXXX
    CYGNUM_HAL_ISR_MIN
    CYGNUM_HAL_ISR_MAX
    CYGNUM_HAL_ISR_COUNT

    CYGNUM_HAL_EXCEPTION_XXXX
    CYGNUM_HAL_EXCEPTION_MIN
    CYGNUM_HAL_EXCEPTION_MAX
    CYGNUM_HAL_EXCEPTION_COUNT

All possible VSR, interrupt and exception vectors are specified here, together with maximum and minimum values for range checking. While the VSR and exception numbers will be defined in this file, the interrupt numbers will normally be defined in the variant or platform HAL file that is included by this header.

There are two ranges of numbers, those for the vector service routines and those for the interrupt service routines. The relationship between these two ranges is undefined, and no equivalence should be assumed if vectors from the two ranges coincide.

The VSR vectors correspond to the set of exception vectors that can be delivered by the CPU architecture, many of these will be internal exception traps. The ISR vectors correspond to the set of external interrupts that can be delivered and are usually determined by extra decoding of the interrupt controller by the interrupt VSR.

Where a CPU supports synchronous exceptions, the range of such exceptions allowed are defined by `CYGNUM_HAL_EXCEPTION_MIN` and `CYGNUM_HAL_EXCEPTION_MAX`. The `CYGNUM_HAL_EXCEPTION_XXXX` definitions are standard names used by target independent code to test for the presence of particular exceptions in the architecture. The actual exception numbers will normally correspond to the VSR exception range. In future other exceptions generated by the system software (such as stack overflow) may be added.

`CYGNUM_HAL_ISR_COUNT`, `CYGNUM_HAL_VSR_COUNT` and `CYGNUM_HAL_EXCEPTION_COUNT` define the number of ISRs, VSRs and EXCEPTIONs respectively for the purposes of defining arrays etc. There might be a translation from the supplied vector numbers into array offsets. Hence `CYGNUM_HAL_XXX_COUNT` may not simply be `CYGNUM_HAL_XXX_MAX` - `CYGNUM_HAL_XXX_MIN` or `CYGNUM_HAL_XXX_MAX`+1.

## Interrupt state control

    CYG_INTERRUPT_STATE
    HAL_DISABLE_INTERRUPTS( old )
    HAL_RESTORE_INTERRUPTS( old )
    HAL_ENABLE_INTERRUPTS()
    HAL_QUERY_INTERRUPTS( state )

These macros provide control over the state of the CPUs interrupt mask mechanism. They should normally manipulate a CPU status register to enable and disable interrupt delivery. They should not access an interrupt controller.

`CYG_INTERRUPT_STATE` is a data type that should be used to store the interrupt state returned by `HAL_DISABLE_INTERRUPTS()` and `HAL_QUERY_INTERRUPTS()` and passed to `HAL_RESTORE_INTERRUPTS()`.

`HAL_DISABLE_INTERRUPTS()` disables the delivery of interrupts and stores the original state of the interrupt mask in the variable passed in the `old` argument.

`HAL_RESTORE_INTERRUPTS()` restores the state of the interrupt mask to that recorded in `old`.

`HAL_ENABLE_INTERRUPTS()` simply enables interrupts regardless of the current state of the mask.

`HAL_QUERY_INTERRUPTS()` stores the state of the interrupt mask in the variable passed in the `state` argument. The state stored here should also be capable of being passed to `HAL_RESTORE_INTERRUPTS()` at a later point.

It is at the HAL implementer’s discretion exactly which interrupts are masked by this mechanism. Where a CPU has more than one interrupt type that may be masked separately (e.g. the ARM's IRQ and FIQ) only those that can raise DSRs need to be masked here. A separate architecture specific mechanism may then be used to control the other interrupt types.

## ISR and VSR management

    HAL_INTERRUPT_IN_USE( vector, state )
    HAL_INTERRUPT_ATTACH( vector, isr, data, object )
    HAL_INTERRUPT_DETACH( vector, isr )
    HAL_VSR_SET( vector, vsr, poldvsr )
    HAL_VSR_GET( vector, pvsr )
    HAL_VSR_SET_TO_ECOS_HANDLER( vector, poldvsr )

These macros manage the attachment of interrupt and vector service routines to interrupt and exception vectors respectively.

`HAL_INTERRUPT_IN_USE()` tests the state of the supplied interrupt vector and sets the value of the state parameter to either 1 or 0 depending on whether there is already an ISR attached to the vector. The HAL will only allow one ISR to be attached to each vector, so it is a good idea to use this function before using `HAL_INTERRUPT_ATTACH()`.

`HAL_INTERRUPT_ATTACH()` attaches the ISR, data pointer and object pointer to the given `vector`. When an interrupt occurs on this vector the ISR is called using the C calling convention and the vector number and data pointer are passed to it as the first and second arguments respectively.

`HAL_INTERRUPT_DETACH()` detaches the ISR from the vector.

`HAL_VSR_SET()` replaces the VSR attached to the `vector` with the replacement supplied in `vsr`. The old VSR is returned in the location pointed to by `pvsr`.

`HAL_VSR_GET()` assigns a copy of the VSR to the location pointed to by `pvsr`.

`HAL_VSR_SET_TO_ECOS_HANDLER()` ensures that the VSR for a specific exception is pointing at the eCos exception VSR and not one for RedBoot or some other ROM monitor. The default when running under RedBoot is for exceptions to be handled by RedBoot and passed to GDB. This macro diverts the exception to eCos so that it may be handled by application code. The arguments are the VSR vector to be replaces, and a location in which to store the old VSR pointer, so that it may be replaced at a later point.

## Interrupt controller management

    HAL_INTERRUPT_MASK( vector )
    HAL_INTERRUPT_UNMASK( vector )
    HAL_INTERRUPT_ACKNOWLEDGE( vector )
    HAL_INTERRUPT_CONFIGURE( vector, level, up )
    HAL_INTERRUPT_SET_LEVEL( vector, level )

These macros exert control over any prioritized interrupt controller that is present. If no priority controller exists, then these macros should be empty.

> Note: These macros may not be reentrant, so care should be taken to prevent them being called while interrupts are enabled. This means that they can be safely used in initialization code before interrupts are enabled, and in ISRs. In DSRs, ASRs and thread code, however, interrupts must be disabled before these macros are called. Here is an example for use in a DSR where the interrupt source is unmasked after data processing:

>      ...
>      HAL_DISABLE_INTERRUPTS(old);
>      HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_ETH);
>      HAL_RESTORE_INTERRUPTS(old);
>      ...

`HAL_INTERRUPT_MASK()` causes the interrupt associated with the given vector to be blocked.

`HAL_INTERRUPT_UNMASK()` causes the interrupt associated with the given vector to be unblocked.

`HAL_INTERRUPT_ACKNOWLEDGE()` acknowledges the current interrupt from the given vector. This is usually executed from the ISR for this vector when it is prepared to allow further interrupts. Most interrupt controllers need some form of acknowledge action before the next interrupt is allowed through. Executing this macro may cause another interrupt to be delivered. Whether this interrupts the current code depends on the state of the CPU interrupt mask.

`HAL_INTERRUPT_CONFIGURE()` provides control over how an interrupt signal is detected. The arguments are:

vector

  The interrupt vector to be configured.

level

  Set to `true` if the interrupt is detected by level, and `false` if it is edge triggered.

up

  If the interrupt is set to level detect, then if this is `true` it is detected by a high signal level, and if `false` by a low signal level. If the interrupt is set to edge triggered, then if this is `true` it is triggered by a rising edge and if `false` by a falling edge.

`HAL_INTERRUPT_SET_LEVEL()` provides control over the hardware priority of the interrupt. The arguments are:

vector

  The interrupt whose level is to be set.

level

  The priority level to which the interrupt is to set. In some architectures the masking of an interrupt is achieved by changing its priority level. Hence this function, `HAL_INTERRUPT_MASK()` and `HAL_INTERRUPT_UNMASK()` may interfere with each other.

## Clock control

    HAL_CLOCK_INITIALIZE( period )
    HAL_CLOCK_RESET( vector, period )
    HAL_CLOCK_READ( pvalue )

These macros provide control over a clock or timer device that may be used by the kernel to provide time-out, delay and scheduling services. The clock is assumed to be implemented by some form of counter that is incremented or decremented by some external source and which raises an interrupt when it reaches a predetermined value.

`HAL_CLOCK_INITIALIZE()` initializes the timer device to interrupt at the given period. The period is essentially the value used to initialize the timer counter and must be calculated from the timer frequency and the desired interrupt rate. The timer device should generate an interrupt every `period` cycles.

`HAL_CLOCK_RESET()` re-initializes the timer to provoke the next interrupt. This macro is only really necessary when the timer device needs to be reset in some way after each interrupt.

`HAL_CLOCK_READ()` reads the current value of the timer counter and puts the value in the location pointed to by `pvalue`. The value stored will always be the number of timer cycles since the last interrupt, and hence ranges between zero and the initial period value. If this is a count-down cyclic timer, some arithmetic may be necessary to generate this value.

## Microsecond Delay

    HAL_DELAY_US(us)

This is an optional definition. If defined the macro implements a busy loop delay for the given number of microseconds. This is usually implemented by waiting for the required number of hardware timer ticks to pass.

This operation should normally be used when a very short delay is needed when controlling hardware, programming FLASH devices and similar situations where a wait/timeout loop would otherwise be used. Since it may disable interrupts, and is implemented by busy waiting, it should not be used in code that is sensitive to interrupt or context switch latencies.

Prev | Home | Next
Architecture Characterization | Up | HAL I/O