To generate an interrupt service routine (ISR) associated with a specific VME interrupt level for the example RTOS (VxWorks®), use the Async Interrupt block. The Async Interrupt block enables the specified interrupt level and installs an ISR that calls a connected function call subsystem.
You can also use the Async Interrupt block in a simulation. It provides an input port that can be enabled and connected to a simulated interrupt source.
Note
The operating system integration techniques that are demonstrated
in this section use one or more blocks the blocks in the vxlib1
library.
These blocks provide starting point examples to help you develop custom
blocks for your target environment.
To generate an ISR, connect an output of the Async Interrupt block to the control input of
A function call subsystem
The input of a Task Sync block
The input to a Stateflow® chart configured for a function call input event
The next figure shows an Async Interrupt block configured to service two interrupt sources. The outputs (signal width 2) are connected to two function call subsystems.
Note the following requirements and restrictions:
The Async Interrupt block supports VME interrupts 1 through 7.
The Async Interrupt block uses the following system calls to the example RTOS (VxWorks):
sysIntEnable
sysIntDisable
intConnect
intLock
intUnlock
tickGet
Execution of large subsystems at interrupt level can have a significant impact on interrupt response time for interrupts of equal and lower priority in the system. As a general rule, it is best to keep ISRs as short as possible. Connect only function call subsystems that contain a small number of blocks to an Async Interrupt block.
A better solution for large subsystems is to use the Task
Sync block to synchronize the execution of the function call
subsystem to a RTOS task. The Task Sync block is placed
between the Async Interrupt block and the function
call subsystem. The Async Interrupt block then installs
the Task Sync block as the ISR. The ISR releases a
synchronization semaphore (performs a semGive
)
to the task, and returns immediately from interrupt level. The task
is then scheduled and run by the example RTOS (VxWorks). See Spawn and Synchronize Execution of RTOS Task for more information.
This section describes a dual-model approach to the development and implementation of real-time systems that include ISRs. In this approach, you develop one model that includes a plant and a controller for simulation, and another model that only includes the controller for code generation. Using a Simulink® library, you can implement changes to both models simultaneously. The next figure shows how changes made to the plant or controller, both of which are in a library, are propagated to the models.
Dual-Model Use of Async Interrupt Block for Simulation and Code Generation
A single-model approach is also possible.
In this approach, the Plant component of the model is active only
in simulation. During code generation, the Plant components are effectively
switched out of the system and code is generated only for the interrupt
block and controller parts of the model. For an example of this approach,
see the rtwdemo_async
model.
The following block diagram shows a simple model that illustrates the dual-model approach to modeling. During simulation, the Pulse Generator blocks provide simulated interrupt signals.
The simulated interrupt signals are routed through the Async Interrupt block's input port. Upon receiving a simulated interrupt, the block calls the connected subsystem.
During simulation, subsystems connected to Async Interrupt block outputs are executed in order of their priority in the example RTOS (VxWorks). In the event that two or more interrupt signals occur simultaneously, the Async Interrupt block executes the downstream systems in the order specified by their interrupt levels (level 7 gets the highest priority). The first input element maps to the first output element.
You can also use the Async Interrupt block in
a simulation without enabling the simulation input. In such a case,
the Async Interrupt block inherits the base rate of
the model and calls the connected subsystems in order of their priorities
in the RTOS. (In this case, the Async Interrupt block
behaves as if all inputs received a 1
simultaneously.)
In the generated code for the sample model,
Ground blocks provide input signals to the Environment Controller block
The Async Interrupt block does not use its simulation input
The Ground blocks drive control input of the Environment Controller block, so code is not generated for that signal path. The code generator does not produce code for blocks that drive the simulation control input to the Environment Controller block because that path is not selected during code generation. However, the sample times of driving blocks for the simulation input to the Environment Controller block contribute to the sample times supported in the generated code. To avoid including unnecessary sample times in the generated code, use the sample times of the blocks driving the simulation input in the model where generated code is intended.
Standalone functions are installed as ISRs and the interrupt vector table is as follows:
Offset | |
---|---|
192 | &isr_num1_vec192() |
193 | &isr_num2_vec193() |
Consider the code generated from this model, assuming that the Async Interrupt block parameters are configured as shown in the next figure.
In the generated code, the Async Interrupt block
installs the code in the Subsystem blocks as interrupt service routines.
The interrupt vectors for IRQ1
and IRQ2
are
stored at locations 192
and 193
relative
to the base of the interrupt vector table, as specified by the VME
interrupt vector offset(s) parameter.
Installing an ISR requires two RTOS (VxWorks) calls, int_connect
and sysInt_Enable
.
The Async Interrupt block inserts these calls in the
function,
as shown in the following code excerpt.model
_initialize
/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Connect and enable ISR function: isr_num1_vec192 */ if( intConnect(INUM_TO_IVEC(192), isr_num1_vec192, 0) != OK) { printf("intConnect failed for ISR 1.\n"); } sysIntEnable(1); /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Connect and enable ISR function: isr_num2_vec193 */ if( intConnect(INUM_TO_IVEC(193), isr_num2_vec193, 0) != OK) { printf("intConnect failed for ISR 2.\n"); } sysIntEnable(2);
The hardware that generates the interrupt is not configured
by the Async Interrupt block. Typically, the interrupt
source is a VME I/O board, which generates interrupts for specific
events (for example, end of A/D conversion). The VME interrupt level
and vector are set up in registers or by using jumpers on the board.
You can use the mdlStart
routine of a user-written
device driver (S-function) to set up the registers and enable interrupt
generation on the board. You must match the interrupt level and vector
specified in the Async Interrupt block dialog to the
level and vector set up on the I/O board.
The actual ISR generated for IRQ1
in the
RTOS (VxWorks) is listed below.
/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ void isr_num1_vec192(void) { int_T lock; FP_CONTEXT context; /* Use tickGet() as a portable tick counter example. A much higher resolution can be achieved with a hardware counter */ Async_Code_M->Timing.clockTick2 = tickGet(); /* disable interrupts (system is configured as non-ive) */ lock = intLock(); /* save floating point context */ fppSave(&context); /* Call the system: <Root>/Subsystem A */ Count(0, 0); /* restore floating point context */ fppRestore(&context); /* re-enable interrupts */ intUnlock(lock); }
There are several features of the ISR that should be noted:
Because of the setting of the Preemption
Flag(s) parameter, this ISR is locked; that is, it cannot
be preempted by a higher priority interrupt. The ISR is locked and
unlocked in the example RTOS (VxWorks) by the int_lock
and int_unlock
functions.
The connected subsystem, Count
,
is called from within the ISR.
The Count
function executes algorithmic
(model) code. Therefore, the floating-point context is saved and restored
across the call to Count
.
The ISR maintains its own absolute time counter, which is distinct from other periodic base rate or subrate counters in the system. Timing data is maintained for the use of any blocks executed within the ISR that require absolute or elapsed time.
See Timers in Asynchronous Tasks for details.
The model's termination function disables the interrupts in the RTOS (VxWorks):
/* Model terminate function */ void Async_Code_terminate(void) { /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Disable interrupt for ISR system: isr_num1_vec192 */ sysIntDisable(1); /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Disable interrupt for ISR system: isr_num2_vec193 */ sysIntDisable(2); }