Main Content

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 rtwdemo_async_mdlreftop.

open_system('rtwdemo_async_mdlreftop');

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 block

  • A 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 roo-level Inport block, allows a reference model to receive asynchronous function-call input. To use the block:

  1. Connect the Asynchronous Task Specification block to the output port of the root-level Inport block that outputs a function-call trigger.

  2. Select the Output function call parameter of the Inport block to specify that it accepts function-call signals.

  3. On the parameters dialog box for the Asynchronous Task Specification block, set the task priority for the asynchronous task associated with an Inport block. Specify an integer or []. If you specify an integer, it must match the priority of the interrupt initiated by the Async 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. Async Interrupt block and Task Sync block generated code is for the example RTOS (VxWorks). However, you can modify the blocks to generate code for another run-time environment.

1. Create a temporary folder for the build and inspection process.

currentDir = pwd;
[~,cgDir] = rtwdemodir();

2. Build the model.

rtwbuild('rtwdemo_async_mdlreftop');
### 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: rtwdemo_async_mdlrefbot
### Starting build procedure for: rtwdemo_async_mdlreftop
Warning: Simulink Coder: The tornado.tlc target will be removed in a future release.

### Successful completion of code generation for: rtwdemo_async_mdlreftop

Build Summary

Code generation targets built:

Model                    Action          Rebuild Reason                             
====================================================================================
rtwdemo_async_mdlrefbot  Code generated  rtwdemo_async_mdlrefbot.c does not exist.  

Top model targets built:

Model                    Action          Rebuild Reason                                    
===========================================================================================
rtwdemo_async_mdlreftop  Code generated  Code generation information file does not exist.  

2 of 2 models built (0 models already up to date)
Build duration: 0h 0m 51.204s

Review Initialization Code

Open the generated source file rtwdemo_async_mdlreftop.c. The initialization code connects and enables ISR isr_num1_vec192 for interrupt 1 and ISR isr_num2_vec193 for interrupt 2.

cfile = fullfile(cgDir, 'rtwdemo_async_mdlreftop_tornado_rtw', 'rtwdemo_async_mdlreftop.c');
rtwdemodbtype(cfile, ...
    'static void rtwdemo_async_mdlreftop_initialize(void)', ...
    '/* Model terminate function */', ... 
    1, 0);
static void rtwdemo_async_mdlreftop_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' */

  /* SystemInitialize for 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'
   */
  rtwdemo_async_mdlrefbot_Init(&rtwdemo_async_mdlreftop_Y.Out1);
  rtwdemo_async_mdlrefbot_Enable();
}

Review ISR Code

In the generated source file rtwdemo_async_mdlreftop.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(cgDir, 'rtwdemo_async_mdlreftop_tornado_rtw', 'rtwdemo_async_mdlreftop.c');
rtwdemodbtype(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'
     */
    rtwdemo_async_mdlrefbot_Interrupt1(&rtwdemo_async_mdlreftop_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'
     */
    rtwdemo_async_mdlrefbot_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(cgDir, 'rtwdemo_async_mdlreftop_tornado_rtw', 'rtwdemo_async_mdlreftop.c');
rtwdemodbtype(cfile, ...
    'static void rtwdemo_async_mdlreftop_terminate(void)', ...
    '/*========================================================================*', ... 
    1, 0);
static void rtwdemo_async_mdlreftop_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' */
}

Related Information

bdclose('rtwdemo_async_mdlreftop');
rtwdemoclean;
cd(currentDir)

Related Topics