μT-Kernel/SM interrupt management functions are functions for disabling or enabling external interrupt, retrieving interrupt disable status, controlling interrupt controller, etc.
Interrupt handling is largely hardware-dependent, different on each system, and therefore difficult to standardize. The following are given as standard specification, but it may not be possible to follow these exactly on all systems. Implementors should comply with these specifications as much as possible; but where implementation is not feasible, full compliance is not mandatory. If functions not in the standard specification are added, however, the function names must be different from those given here. In any case, DI, EI, and isDI must be implemented in accordance with the standard specification.
Interrupt management functions are provided as library functions or C language macros. These can be called from a task-independent portion and while dispatching and interrupts are disabled.
These functions control the external interrupt mask flag or interrupt mask level in the CPU. Generally speaking, interrupt controller is not touched.
DI disables all the external interrupts and EI enables them. After DI is issued and until EI is issued, the system is in external interrupt disabled state. In this state, an indivisible processing can be performed since no interruption occurs and no dispatching takes place.
There are a few restrictions about the API to control CPU interrupt and the external interrupt disabled state.
CPU interrupt control API is usually implemented as C language compile time macro to set the external interrupt mask flag or interrupt mask level inside the CPU. Hence, this API can be invoked only in the privileged level that can access and control hardware directly. The precise meaning of the level is implementation-dependent.
CPU interrupt control API only sets CPU's external interrupt mask flag or interrupt mask level only. Hence, generally speaking, except for some implementations, the execution of these APIs will not cause delayed dispatching.
There are restrictions on the available APIs in the external interrupt disabled state. API that puts the calling task into waiting state cannot be invoked. The system should return E_CTX. However, the proper error checking to return E_CTX is implementation-dependent. The following APIs of μT-Kernel/SM, Interrupt Management Functions and I/O Port Access Support Functions, can be invoked even when external interrupt is disabled. Whether other APIs can be invoked when external interrupt is disabled is implementation-dependent.
System timer interrupt is disabled in the external interrupt disabled state. Hence, no timeout occurs, and no time event handler processing occurs.
Additional Notes | |
---|---|
The APIs for controlling CPU interrupt is meant for device drivers to perform indivisible execution for low-level control such as hardware by disabling external interrupt temporarily. However, the disabling of external interrupt reduces the system responsiveness and the real-time performance suffers. So the indivisible operation should be finished quickly and external interrupt disabled state should be exited soon. External interrupt disabled state entered by DI is very similar to task-independent portion. Even if an API that would usually cause dispatch such as tk_wup_tsk is invoked, dispatching does not occur. Afterward, when EI is issued to return to external interrupt enabled state, the delayed dispatching associated with EI do not occur generally (except for some implementations). As a result, after EI is issued, we may have an unexpected situation where a lower priority task continues to run even though a higher priority task in READY state exists. To avoid the unexpected situation, when a program needs to issue an API that causes dispatching during the time interval that starts with DI and ends with EI, it is recommended to surround the interval of external interrupt disabled state by a pair of tk_dis_dsp and tk_ena_dsp. Namely, the APIs should be issued in the following order: tk_dis_dsp → DI → API that causes dispatching → EI → tk_ena_dsp. With this order of issuing the APIs, external interrupt and dispatching are disabled between DI and EI. Only dispatching is disabled bewteen tk_dis_dsp and tk_ena_dsp. And at the timing of the last tk_ena_dsp, delayed dispatching does take place. Hence, the unexpected situation mentioned in the preceding sentences is corrected after all. Issueing the APIs in this order guarantees the same system behavior that is not implementation-dependent. |
None.
None.
Controls the external interrupt flag in the CPU and disables all external interrupts. Also stores the flag state in intsts
before disabling interrupt.
intsts
is not a pointer. Write a variable directly. Generally, this API is defined as a C language macro.
Regarding the APIs that can be issued during external interrupt disabled state, see the explanation at the beginning of the Section called CPU Interrupt Control.
None.
None.
Controls the external interrupt flag in the CPU and reverts the flag state to intsts
. That is, this API reverts the flag state to the state before disabling external interrupts by the previously executed DI(intsts).
If the state before executing DI(intsts) was the external-interrupt-enabled, the subsequent EI(intsts) enables external interrupts. On the other hand, if the state was already interrupt-disabled at the time DI(intsts) was executed, interrupt is not enabled by EI(intsts). However, if 0 is specified in intsts
, the external interrupt flag in the CPU is set to the interrupt-enable state.
intsts
must be either the value saved by DI or 0. If any other value is specified, the subsequent correct behavior is not guaranteed.
The specifications pays attention to the execution efficiency to minimize overhead. Therefore, this API is usually implemented using assembly language or C language macro. This API controls the external interrupt mask flag in the CPU only and does nothing else. No error result is returned. Hence, except for some implementations, the execution of this API will not cause delayed dispatching, generally speaking.
None.
Checks the external interrupt flag in the CPU that was stored in intsts
by the previously executed DI, and returns TRUE(a non-zero value) if the flag status is determined as the interrupt-disabled, or FALSE otherwise.
intsts
must be the value saved by DI. If any other value is specified, the subsequent correct behavior is not guaranteed.
This specification pay attention to the execution efficiency to minimize overhead. Therefore, this API is usually implemented using assembly language or C language macro.
None.
None.
Only when all the service profile items below are set to be effective, this API can be used.
Set interrupt mask level of CPU and disable interrupts that have lower interrupt priority than level
. Interrupts that have interrupt priority that is equal to level
or higher are enabled.
When INTLEVEL_DI is specified to level
, the interrupt mask level within the interrupt controller is set to disable all external interrupts at all priority levels. Generally speaking, this is the same state of the system after DI is called.
When INTLEVEL_EI is specified to level
, the mask level within the interrupt controller is set to enable all external interrupts at all priority levels. Generally speaking, this is the same state of the system after EI(0) is called.
While interrupts are disabled due to the execution of this API, dispatch may be delayed, as in the case of the interrupt handler's being executed, until the interrupts are enabled again.
The range of value that can be specified by level
and the concrete value of INTLEVEL_DI
are implementation-dependent. The ordering relation of the interrupt level as numeric value and the interrupt priority is implementation-dependent. Generally speaking, the specification about these is decided based on the CPU architecture.
The specifications pays attention to the execution efficiency to minimize overhead. Therefore, this API is usually implemented using assembly language or C language macro. This API controls the interrupt mask level in the CPU only and does nothing else. No error result is returned. Hence, except for some implementations, the execution of this API will not cause delayed dispatching, generally speaking.
"Interrupt mask level" is defined to be the lower bound of interrupt priority level (interrupt level) for external interrupts that are enabled (masked). External interrupts with priorities equal to or higher than the interrupt mask level are enabled.
This API sets the interrupt mask level within CPU, and has a similar function as that of SetCtrlIntLevel which sets the interrupt mask level within the interrupt controller. The former affects the result of interrupt enable/disable setting done by DI, EI. The latter has nothing to do with this.
This API sets the interrupt mask level within CPU without regard to the previous setting. Note that there are both cases of either the increase of the disabled interrupts, or the decrease of disabled interrupts after the execution of this API.
None.
None.
Only when all the service profile items below are set to be effective, this API can be used.
Get the current value of interrupt mask level in CPU, and return it as the value of return parameter level
.
The range of value that can be specified by level
is implementation-dependent.
See the explanation and additional notes in SetCpuIntLevel.
These functions control the interrupt controller. Generally they do not perform any operation with respect to the CPU interrupt flag.
None.
None.
Only when all the service profile items below are set to be effective, this API can be used.
Additionally, the following service profile items are related to this API.
Enable interrupt with interrupt number, intno
. On a system where interrupt priority level can be specified, level
is used to specify the interrupt priority level.
The interrupt number that can be specified in intno
is limited to a number that can be usable by tk_def_int and at the same time, an interrupt number that is controlled by the interrupt controller. The subsequent correct behavior of the system as a whole when an invalid intno
is specified is not guaranteed.
Either the support of level
or the support without level
is provided.
This API does not check for error just as other interrupt-related APIs do not.
None.
None.
Only when all the service profile items below are set to be effective, this API can be used.
Disable interrupt with the interrupt number, intno
. Generally speaking, an interrupt that is disabled will become pending and, once it is enabled by EnableInt, an interrupt is generated. If it is desired to cancel an interrupt condition that became pending because the interrupt was disabled, ClearInt must be called.
The interrupt number that can be specified in intno
is limited to a number that can be usable by tk_def_int and at the same time, an interrupt number that is controlled by the interrupt controller. The subsequent correct behavior of the system as a whole when an invalid intno
is specified is not guaranteed.
This API does not check for error just as other interrupt-related APIs do not.
None.
None.
Only when all the service profile items below are set to be effective, this API can be used.
If an interrupt with interrupt number, intno
, has been generated, it is cleared.
The interrupt number that can be specified in intno
is limited to a number that can be usable by tk_def_int and at the same time, an interrupt number that is controlled by the interrupt controller. The subsequent correct behavior of the system as a whole when an invalid intno
is specified is not guaranteed.
This API does not check for errors since it focuses on the execution efficiency to minimize overhead.
None.
None.
Only when all the service profile items below are set to be effective, this API can be used.
Issue EOI to Interrupt Controller. intno
must identify an interrupt that is the target of EOI. Generally this must be executed at the end of an interrupt handler.
The interrupt number that can be specified in intno
is limited to a number that can be usable by tk_def_int and at the same time, an interrupt number that is controlled by the interrupt controller. The subsequent correct behavior of the system as a whole when an invalid intno
is specified is not guaranteed.
This API does not check for errors since it focuses on the execution efficiency to minimize overhead.
None.
Only when all the service profile items below are set to be effective, this API can be used.
Check to see if an interrupt with interrupt number, intno
, has been generated. If an interrupt with the interrupt number, intno
, has been generated, TRUE (a non-zero value) is returned, and if it has not, then FALSE is returned.
None.
None.
Only when all the service profile items below are set to be effective, this API can be used.
Set the interrupt mode of interrupt specified by intno
to mode
.
The interrupt number that can be specified in intno
is limited to a number that can be usable by tk_def_int and at the same time, an interrupt number that is controlled by the interrupt controller. The subsequent correct behavior of the system as a whole when an invalid intno
is specified is not guaranteed.
The settable modes and how to specify mode
are implementation-dependent. The following is an example of settable modes:
mode := (IM_LEVEL || IM_EDGE) | (IM_HI || IM_LOW)
#define IM_LEVEL 0x0002 /* Level trigger */ #define IM_EDGE 0x0000 /* Edge trigger */ #define IM_HI 0x0000 /* H level/Interrupt at rising edge */ #define IM_LOW 0x0001 /* L level/Interrupt at falling edge */
If invalid mode
is specified, the subsequent correct behavior is not guaranteed.
This API does not check for error just as other interrupt-related APIs do not.
None.
None.
Only when all the service profile items below are set to be effective, this API can be used.
Set interrupt mask level of the interrupt controller and disable interrupts that have lower interrupt priority than level
. Interrupts that have interrupt priority that is equal to level
or higher are enabled.
When INTLEVEL_DI is specified to level
, the interrupt mask level within the interrupt controller is set to disable all external interrupts at all priority levels.
When INTLEVEL_EI is specified to level
, the mask level within the interrupt controller is set to enable all external interrupts at all priority levels.
While interrupts are disabled due to the execution of this API, dispatch may be delayed, as in the case of the interrupt handler's being executed, until the interrupts are enabled again.
The range of value that can be specified by level
and the concrete value of INTLEVEL_DI
are implementation-dependent. The ordering relation of the interrupt level as numeric value and the interrupt priority is implementation-dependent. Generally speaking, the specification about these is decided based on the CPU architecture.
See the additional notes for SetCpuIntLevel.
This API sets the interrupt mask level within interrupt controller without regard to the previous setting. Note that there are both cases of either the increase of the disabled interrupts, or the decrease of disabled interrupts after the execution of this API.
This API does not check for errors since it focuses on the execution efficiency to minimize overhead.
None.
None.
Only when all the service profile items below are set to be effective, this API can be used.
This returns the current interrupt mask level configured inside the interrupt controller, and return it in the return parameter level
.
The range of value that can be specified by level
is implementation-dependent.
See the additional notes for SetCpuIntLevel.