Interrupt Management Functions

Interrupt management functions are for defining and manipulating handlers for external interrupts and CPU exceptions.

An interrupt handler runs as a task-independent portion. System calls can be invoked in a task-independent portion in the same way as in a task portion, but the following restriction applies to system call issuing in a task-independent portion.

During task-independent portion execution, task switching (dispatching) does not occur. If system call processing results in a dispatch request, the dispatch is delayed until processing leaves the task-independent portion. This is called delayed dispatching.

tk_def_int - Define Interrupt Handler

C Language Interface

#include <tk/tkernel.h>

ER ercd = tk_def_int(UINT intno, CONST T_DINT *pk_dint);

Parameter

UINT intno Interrupt NumberInterrupt number
CONST T_DINT* pk_dint Packet to Define Interrupt HandlerInterrupt handler definition information

pk_dint Detail:

ATR intatr Interrupt Handler AttributeInterrupt handler attribute
FP inthdr Interrupt Handler AddressInterrupt handler address
(Other implementation-dependent parameters may be added beyond this point.)

Return Parameter

ER ercd Error CodeError code

Error Code

E_OK Normal completion
E_NOMEM Insufficient memory (memory for control block cannot be allocated)
E_RSATR Reserved attribute (intatr is invalid or cannot be used)
E_PAR Parameter error (intno, pk_dint, or inthdr is invalid or cannot be used)

Valid Context

Task portionQuasi-task portionTask-independent portion
YESYESNO

Related Service Profile Items

TK_SUPPORT_ASM Support for specifying TA_ASM for interrupt handler attribute

Description

"Interrupts" include both external interrupts from devices and interrupts due to CPU exceptions.

Defines an interrupt handler for the interrupt number intno to enable use of the interrupt handler. This system call maps the interrupt number specified by intno to the address and attributes of the interrupt handler.

intno is the number used to distinguish different interrupts. Its specific meaning is defined for each implementation, but generally the interrupt number used by the interrupt mechanism of the CPU hardware (such as IRQ number) is used as it is, or any number that can be mapped to such number is used.

intatr indicates system attributes in its lower bits and implementation-dependent attributes in its higher bits. The system attribute part of intatr is specified as follows.


intatr := (TA_ASM || TA_HLNG)

TA_ASM The handler is written in assembly language
TA_HLNG The handler is written in high-level language


#define TA_ASM          0x00000000      /* assembly language program */
#define TA_HLNG         0x00000001      /* high-level language program */

As a rule, the kernel is not involved in the starting of a TA_ASM attribute interrupt handler. When an interrupt is raised, the interrupt handling function in the CPU hardware directly starts the interrupt handler defined by this system call (depending on the implementation, processing by program may be included). Accordingly, processing for saving and restoring registers used by the interrupt handler is necessary at the beginning and end of the interrupt handler. An interrupt handler is terminated by execution of the tk_ret_int system call or by the CPU interrupt return instruction (or an equivalent mechanism).

Support of a mechanism for return from an interrupt handler without using tk_ret_int and hence without kernel intervention is mandatory. Note that if tk_ret_int is not used, delayed dispatching does not need to be performed.

Support for return from an interrupt handler using tk_ret_int is also mandatory, and in this case delayed dispatching must be performed.

When the TA_HLNG attribute is specified, the interrupt handler is started via a high-level language support routine. The high-level language support routine takes care of saving and restoring register values. The interrupt handler terminates by a return from a C language function. The interrupt handler takes the following format when the TA_HLNG attribute is specified.


void inthdr( UINT intno )
{
        /*
                Interrupt Handling
        */

        return; /* Exit interrupt handler */
}

The parameter intno passed to an interrupt handler is the interrupt number identifying the interrupt that was raised, and is the same as that specified with tk_def_int. Depending on the implementation, other information about the interrupt may be passed in addition to intno. If such information is used, it must be defined for each implementation in the second parameter or subsequent parameters passed to the interrupt handler.

If the TA_HLNG attribute is specified, it is assumed that the CPU interrupt flag will be set to interrupts disabled state from the time the interrupt is raised until the interrupt handler is called. In other words, as soon as an interrupt is raised, multiple interrupts are disabled, and this state remains when the interrupt handler is called. If multiple interrupts are to be allowed, the interrupt handler must include processing that handles multiple interrupts by manipulating the CPU interrupt flag.

Also in the case of the TA_HLNG attribute, upon entry into the interrupt handler, issuing system call must be possible. Note, however, that assuming standard provision of the functionality described above, extensions are allowed such as adding a function for entering an interrupt handler with multiple interrupts enabled.

When the TA_ASM attribute is specified, the state upon entry into the interrupt handler shall be defined for each implementation. Such matters as the stack and register status upon interrupt handler entry, whether system calls can be made, the method of invoking system calls, and the method of returning from the interrupt handler without kernel intervention must all be defined explicitly.

In the case of the TA_ASM attribute, depending on the implementation there may be cases where interrupt handler execution is not considered to be a task-independent portion. In such a case the following points need to be noted carefully.

  • If interrupts are enabled, there is a possibility that task dispatching will occur.

  • When a system call is invoked, it will be processed as having been called from a task portion or quasi-task portion.

If a method is provided for performing some kind of operation in an interrupt handler to detected whether it runs as task-independent portion, that method shall be announced for each implementation.

Even if a system call is invoked from an interrupt handler and this causes the task in RUNNING state up to that time to go to another state, with a different task going to RUNNING state, dispatching (task switching) does not occur while the interrupt handler is running. Completion of execution of the interrupt handler has precedence even if dispatching is necessary; only when the interrupt handler terminates does the dispatch take place. In other words, a dispatch request that is generated while an interrupt handler is running is not processed immediately, but is delayed until the interrupt handler terminates. This is called delayed dispatching.

An interrupt handler runs as a task-independent portion. As such, it is not possible to call in an interrupt handler a system call that can enter WAITING state, or one that is intended for the invoking task.

When pk_dint = NULL is set, a previously defined interrupt handler is canceled. When the handler definitions are canceled, the default handler defined by the system is used.

It is possible to redefine an interrupt handler for an interrupt number for which a handler is already defined. It is not necessary first to cancel the definition for that number. Defining a new handler for a intno already having an interrupt handler defined does not return error.

Additional Notes

The various specifications governing the TA_ASM attribute are mainly concerned with realizing an interrupt hook. For example, when an exception is raised due to illegal address access, ordinarily an interrupt handler defined in a higher-level program detects this and performs the error processing; but in the case of debugging, in place of error processing by a higher-level program, the default interrupt handler defined by the system may perform the processing and starts a debugger. In this case, the interrupt handler defined by high-level program hooks the default interrupt handler defined by the system. And, according to the situation, the handler either passes the interrupt handling to a system program such as a debugger, or it just processes it for itself.

tk_ret_int - Return from Interrupt Handler

C Language Interface

#include <tk/tkernel.h>

void tk_ret_int(void);

Although this system call is defined in the form of a C language interface, it will not be called in this format if a high-level language support routine is used.

Return Parameter

Does not return to the context issuing the system call.

Error Codes

The following kind of error may be detected, but no return is made to the context issuing the system call even if the error is detected. For this reason the error code cannot be passed directly as a system call return parameter. The behavior in case an error occurs is implementation-dependent.

E_CTX Context error (issued from other than an interrupt handler (implementation-dependent error))

Valid Context

Task portionQuasi-task portionTask-independent portion
NONOYES

Related Service Profile Items

Only when all the service profile items below are set to be effective, this system call can be used.

TK_SUPPORT_ASM Support for specifying TA_ASM for interrupt handler attribute

Description

Exits from an interrupt handler.

System calls invoked from an interrupt handler do not result in dispatching while the handler is running; instead, the dispatching is delayed until tk_ret_int is called ending the interrupt handler processing(delayed dispatching). Accordingly, tk_ret_int results in the processing of all dispatch requests made while the interrupt handler was running.

tk_ret_int is invoked only if the interrupt handler was defined specifying the TA_ASM attribute. In the case of a TA_HLNG attribute interrupt handler, the functionality equivalent to tk_ret_int is executed implicitly in the high-level language support routine, so tk_ret_int is not (must not be) called explicitly.

As a rule, the kernel is not involved in the starting of a TA_ASM attribute interrupt handler. When an interrupt is raised, the defined interrupt handler is started directly by the CPU hardware interrupt processing function. The saving and restoring of registers used by the interrupt handler must therefore be taken care of in the interrupt handler.

For the same reason, the stack and register states at the time tk_ret_int is issued must be the same as those at the time of entry into the interrupt handler. Because of this, in some cases function codes cannot be used in tk_ret_int, in which case tk_ret_int can be implemented using a trap instruction of another vector separate from that used for other system calls.

Additional Notes

tk_ret_int is a system call that does not return to the context from which it was called. Even if an error code is returned when an error of some kind is detected, normally no error checking is performed in the context from which the system call was invoked, leaving the possibility that the program will hang. For this reason these system calls do not return even if error is detected.

Using an assembly language return-from-interrupt instruction instead of tk_ret_int to exit the interrupt handler is possible if it is clear no dispatching will take place on return from the handler (the same task is guaranteed to continue executing), or if there is no need for dispatching to take place.

Depending on the CPU architecture and method of implementing the kernel, it may be possible to perform delayed dispatching even when an interrupt handler exits using an assembly language return-from-interrupt instruction. In such cases, it is permissible for the assembly language return-from-interrupt instruction to be interpreted as if it were a tk_ret_int system call.

Performing of E_CTX error checking when tk_ret_int is called from a time event handler is implementation-dependent. Depending on implementation, control may return from a different type of handler immediately.