Pass Asynchronous Events in RTOS as Input to a Referenced Model
This example shows how to simulate and generate code for asynchronous events on a real-time multitasking system.
About the Example Model
Open the example model AsynchronousEventsTop
.
open_system('AsynchronousEventsTop');
The model simulates an interrupt source and includes an Async Interrupt
block and referenced model. The Async Interrupt
block creates two Versa Module Eurocard (VME) interrupt service routines (ISRs) that pass interrupt signals to Inport blocks 1 and 2 of the referenced model.
You can place an Async Interrupt
block between a simulated interrupt source and one of these model elements:
Function call subsystem
Task Sync
blockA Stateflow® chart configured for a function call input event
A referenced model with an
Inport
block that connects to one of the preceding model elements
In this example model, the Async Interrupt
block passes asynchronous events (function-call trigger signals), Interrupt1
and Interrupt2
, to the referenced model through Inport
blocks 1 and 2.
The code generator produces code that is tailored for the VxWorks operating system. Reconfigure the Async Interrupt
block to generate code for an alternative application run-time environment.
Open the referenced model. The referenced model includes the two Inport
blocks that receive the interrupts, each connected to an Asynchronous Task Specification
block, function-call subsystems Count and Algorithm, and Rate Transition
blocks. The Asynchronous Task Specification
block, in combination with a root-level Inport
block, allows a reference model to receive asynchronous function-call input. To use the block:
Connect the
Asynchronous Task Specification
block to the output port of the root-levelInport
block that outputs a function-call trigger.Select the Output function call parameter of the
Inport
block to specify that it accepts function-call signals.On the parameters dialog box for the
Asynchronous Task Specification
block, set the task priority for the asynchronous task associated with anInport
block. Specify an integer or []. If you specify an integer, it must match the priority of the interrupt initiated by theAsync Interrupt
block in the parent model. If you specify [], the priorities do not have to match.
The Asynchronous Task Specification
block for the higher priority interrupt, interrupt1
, connect to function-call subsystem Count
. Count
represents a simple interrupt service routine (ISR). The second Asynchronous Task Specification
block connect to the subsystem Algorithm
, which includes more substance. It includes multiple blocks and produces two output values. Both subsystems execute at interrupt level.
For each interrupt level specified for the Async Interrupt
block in the parent model, the block generates a VME ISR that executes the connected subsystem, Task Sync
block, or chart.
In the example top model, the Async Interrupt
block is configured for VME interrupts 1 and 2, using interrupt vector offsets 192 and 193. Interrupt 1 is wired to trigger subsystem Count
. Interrupt 2 is wired to trigger subsystem Algorithm
.
The Rate Transition
blocks handle data transfers between ports that operate at different rates. In two instances, the blocks protect data transfers (prevent them from being preempted and corrupted). In the other instance, no special behavior occurs.
Data Transfer Assumptions
Data transfers occur between one reading task and one writing task.
A read or write operation on a byte-sized variable is atomic.
When two tasks interact, only one can preempt the other.
For periodic tasks, the task with the faster rate has higher priority than the task with the slower rate. The task with the faster rate preempts the tasks with slower rates.
Tasks run on a single processor. Time slicing is not allowed.
Processes do not crash and restart, especially while data is being transferred between tasks.
Simulate the Model
Simulate the model. By default, the model is configured to show sample times in different colors. Discrete sample times for input and output appear red and green, respectively. Constants are magenta. Asynchronous interrupts are purple. The Rate Transition
blocks, which are hybrid (input and output sample times can differ), appear yellow.
Generate Code and Report
Generate code and a code generation report for the model. The code generated for the Async Interrupt
and Task Sync
blocks is for the example RTOS (VxWorks). However, you can modify the blocks to generate code for another run-time environment.
Build the model.
slbuild('AsynchronousEventsTop');
### Searching for referenced models in model 'AsynchronousEventsTop'. ### Found 1 model reference targets to update. ### Starting serial model reference code generation build.
Warning: Simulink Coder: The tornado.tlc target will be removed in a future release.
### Successfully updated the model reference code generation target for: AsynchronousEventsRef ### Starting build procedure for: AsynchronousEventsTop
Warning: Simulink Coder: The tornado.tlc target will be removed in a future release.
### Successful completion of code generation for: AsynchronousEventsTop Build Summary Model reference code generation targets: Model Build Reason Status Build Duration ======================================================================================================= AsynchronousEventsRef Target (AsynchronousEventsRef.c) did not exist. Code generated. 0h 0m 18.027s Top model targets: Model Build Reason Status Build Duration =========================================================================================================== AsynchronousEventsTop Information cache folder or artifacts were missing. Code generated. 0h 0m 12.263s 2 of 2 models built (0 models already up to date) Build duration: 0h 0m 36.236s
Review Initialization Code
Open the generated source file AsynchronousEventsTop.c
. The initialization code connects and enables ISR isr_num1_vec192
for interrupt 1 and ISR isr_num2_vec193
for interrupt 2.
cfile = fullfile('AsynchronousEventsTop_tornado_rtw', 'AsynchronousEventsTop.c'); coder.example.extractLines(cfile, ... 'static void AsynchronousEventsTop_initialize(void)', ... '/* Model terminate function */', ... 1, 0);
static void AsynchronousEventsTop_initialize(void) { /* Start for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* 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); /* End of Start for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ }
Review ISR Code
In the generated source file AsynchronousEventsTop.c
, review the code for ISRs isr_num1_vec192
and isr_num2_vec293
. Each ISR:
Disables interrupts.
Saves floating-point context.
Calls the code generated for the subsystem connected to the referenced model
Inport
block that receives the interrupt.Restores floating-point context.
Reenables interrupts.
cfile = fullfile('AsynchronousEventsTop_tornado_rtw', 'AsynchronousEventsTop.c'); coder.example.extractLines(cfile, ... 'void isr_num1_vec192(void)', ... 'time_T rt_SimUpdateDiscreteEvents', ... 1, 0);
void isr_num1_vec192(void) { int_T lock; FP_CONTEXT context; /* disable interrupts (system is configured as non-preemptive) */ lock = intLock(); /* save floating point context */ fppSave(&context); /* Call the system: '<Root>/Model' */ { /* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1_60hz' * Inport: '<Root>/In2_60_hz' * Inport: '<Root>/In3_60hz' * Outport: '<Root>/Out1' * Outport: '<Root>/Out2' * Outport: '<Root>/Out3' */ AsynchronousEventsRef_Interrupt1(&AsynchronousEventsTop_Y.Out1); /* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /* restore floating point context */ fppRestore(&context); /* re-enable interrupts */ intUnlock(lock); } /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ void isr_num2_vec193(void) { FP_CONTEXT context; /* save floating point context */ fppSave(&context); /* Call the system: '<Root>/Model' */ { /* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1_60hz' * Inport: '<Root>/In2_60_hz' * Inport: '<Root>/In3_60hz' * Outport: '<Root>/Out1' * Outport: '<Root>/Out2' * Outport: '<Root>/Out3' */ AsynchronousEventsRef_Interrupt2(); /* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /* restore floating point context */ fppRestore(&context); }
Review Task Termination Code
The Task Sync
block generates the following termination code.
cfile = fullfile('AsynchronousEventsTop_tornado_rtw', 'AsynchronousEventsTop.c'); coder.example.extractLines(cfile, ... 'static void AsynchronousEventsTop_terminate(void)', ... '/*========================================================================*', ... 1, 0);
static void AsynchronousEventsTop_terminate(void) { /* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* 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); /* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ }