Create a Customized Asynchronous Library - MATLAB & Simulink (original) (raw)

This topic describes how to implement asynchronous blocks for use with your target RTOS, using the Async Interrupt and Task Sync blocks as a starting point. Rate Transition blocks are target-independent, so you do not need to develop customized rate transition blocks.

Note

The operating system integration techniques that are demonstrated in this topic use blocks that are in the Interrupt Templates block library. The blocks in that library serve as examples to help you develop custom blocks for a specific target environment.

About Implementing Asynchronous Blocks

You can customize the asynchronous library blocks by modifying the block implementation. These files are

In addition, you need to modify the block masks to remove references specific to the example RTOS (VxWorks®) and to incorporate parameters required by your target RTOS.

Custom block implementation is an advanced topic, requiring familiarity with the Simulink® MEX S-function format and API, and with the Target Language Compiler (TLC). These topics are covered in the following documents:

The following sections discuss the C/C++ and TLC implementations of the asynchronous library blocks, including required SimStruct macros and functions in the TLC asynchronous support library (asynclib.tlc).

Async Interrupt Block Implementation

The source files for the Async Interrupt block are located in_`matlabroot`_/rtw/c/tornado/devices (open):

C MEX Block Implementation

Most of the code in vxinterrupt1.c performs ordinary functions that are not related to asynchronous support (for example, obtaining and validating parameters from the block mask, marking parameters nontunable, and passing parameter data to the_`model`_.rtw file).

The mdlInitializeSizes function uses specialSimStruct macros and SS_OPTIONS settings that are required for asynchronous blocks, as described below.

Note that the following macros cannot be called beforessSetOutputPortWidth is called:

If one of the above macros is called before ssSetOutputPortWidth, the following error message appears:

SL_SfcnMustSpecifyPortWidthBfCallSomeMacro {
S-function '%s' in '%' must set output port %d width using ssSetOutputPortWidth before calling macro %s }

ssSetAsyncTimerAttributes. ssSetAsyncTimerAttributes declares that the block requires a timer, and sets the resolution of the timer as specified for block parameterTimer resolution (seconds).

The function prototype is

ssSetAsyncTimerAttributes(SimStruct *S, double res)

where

The following code excerpt shows the call to ssSetAsyncTimerAttributes.

/* Setup Async Timer attributes */ ssSetAsyncTimerAttributes(S,mxGetPr(TICK_RES)[0]);

ssSetAsyncTaskPriorities. ssSetAsyncTaskPriorities sets the Simulink task priority for blocks executing at each interrupt level, as specified for block parameter Simulink task priority.

The function prototype is

ssSetAsyncTaskPriorities(SimStruct *S, int numISRs, int *priorityArray)

where

The following code excerpt shows the call tossSetAsyncTaskPriorities:

/* Setup Async Task Priorities / priorityArray = malloc(numISRssizeof(int_T)); for (i=0; i<numISRs; i++) { priorityArray[i] = (int_T)(mxGetPr(ISR_PRIORITIES)[i]); } ssSetAsyncTaskPriorities(S, numISRs, priorityArray); free(priorityArray); priorityArray = NULL; }

SS_OPTION Settings. The code excerpt below shows the SS_OPTION settings forvxinterrupt1.c. SS_OPTION_ASYNCHRONOUS_INTERRUPT should be used when a function call subsystem is attached to an interrupt. For more information, see the documentation for SS_OPTION andSS_OPTION_ASYNCHRONOUS in_`matlabroot`_/simulink/include/[simstruc.h](https://mdsite.deno.dev/matlab:edit%28fullfile%28matlabroot,'/simulink/include/simstruc.h'%29%29).

ssSetOptions( S, (SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME | SS_OPTION_ASYNCHRONOUS_INTERRUPT));

If an S-function specifies theSS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME option and inherits a sample time of Inf,​ the code generator determines how to produce code for the block based on whether the block is invariant. A block is invariant if its port signals are invariant. A signal is invariant if it has a constant value during the entire simulation. If you specify a Constant block sample time, do not assume that the port signals are invariant. For more information,​ see Inline Invariant Signals. If the block is not invariant,​ the code generator produces code only in the initialize entry-point function. If the block is invariant,​ the code generator does not produce code for the block.

TLC Implementation

This section discusses each function of vxinterrupt1.tlc, with an emphasis on target-specific features that you will need to change to generate code for your target RTOS.

Generate #include Directives. vxinterrupt1.tlc begins with the statement

%include "vxlib.tlc"

vxlib.tlc is a target-specific file that generates directives to include header files for the example RTOS (VxWorks). You should replace this with a file that generates includes for your target RTOS.

BlockInstanceSetup Function. For each connected output of the Async Interrupt block,BlockInstanceSetup defines a function name for the corresponding ISR in the generated code. The functions names are of the form

where _`num`_ is the ISR number defined for block parameter VME interrupt number(s), and_`offset`_ is an interrupt table offset defined by block parameter VME interrupt vector offset(s).

In a custom implementation, this naming convention is optional.

The function names are cached for use by the Outputs function, which generates the actual ISR code.

Outputs Function. Outputs iterates over the connected outputs of the Async Interrupt block. An ISR is generated for each such output.

The ISR code is cached in the "Functions" section of the generated code. Before generating the ISR, Outputs does the following:

When generating the ISR code, Outputs calls theasynclib function LibNeedAsyncCounter to determine whether a timer is required by the connected subsystem. If so, and if the time source is set to be SS_TIMESOURCE_SELF byssSetTimeSource, LibSetAsyncCounter is called to generate an RTOS (VxWorks) tickGet function call and update the counter. In your implementation, you should generate either an equivalent call to the target RTOS, or generate code to read the a timer register on the target hardware.

Start Function. The Start function generates the required RTOS (VxWorks) calls (int_connect and sysInt_Enable) to connect and enable each ISR. You should replace this with calls to your target RTOS.

Terminate Function. The Terminate function generates the callsysIntDisable to disable each ISR. You should replace this with calls to your target RTOS.

Task Sync Block Implementation

The source files for the Task Sync block are located in_`matlabroot`_/rtw/c/tornado/devices (open). They are

C MEX Block Implementation

Like the Async Interrupt block, the Task Sync block sets up a timer, in this case with a fixed resolution. The priority of the task associated with the block is obtained from block parameter Simulink task priority. The SS_OPTION settings are the same as those used for the Async Interrupt block.

ssSetAsyncTimerAttributes(S, 0.01);

priority = (int_T) (*(mxGetPr(PRIORITY))); ssSetAsyncTaskPriorities(S,1,&priority);

ssSetOptions(S, (SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_ASYNCHRONOUS | SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME)); }

TLC Implementation

Generate #include Directives. vxtask1.tlc begins with the statement

%include "vxlib.tlc"

vxlib.tlc is a target-specific file that generates directives to include header files for the example RTOS (VxWorks). You should replace this with a file that generates includes for your target RTOS.

BlockInstanceSetup Function. The BlockInstanceSetup function derives the task name, block name, and other identifiers used later in code generation. It also checks for and warns about unconnected block conditions, and generates a storage declaration for a semaphore (stopSem) that is used in case of interrupt overflow conditions.

Start Function. The Start function generates the required RTOS (VxWorks) calls to define storage for the semaphore that is used in management of the task spawned by the Task Sync block. Depending on the value of theCodeFormat TLC variable of the target, either a static storage declaration or a dynamic memory allocation call is generated. This function also creates a semaphore (semBCreate) and spawns an RTOS task (taskSpawn). You should replace these with calls to your target RTOS.

Outputs Function. The Outputs function generates an example RTOS (VxWorks) task that waits for a semaphore. When it obtains the semaphore, it updates the block tick timer and calls the downstream subsystem code. Outputs also generates code (called from interrupt level) that grants the semaphore.

Terminate Function. The Terminate function generates the example RTOS (VxWorks) call taskDelete to end execution of the task spawned by the block. You should replace this with calls to your target RTOS.

Note also that if the target RTOS has dynamically allocated memory associated with the task, the Terminate function should deallocate the memory.

asynclib.tlc Support Library

asynclib.tlc is a library of TLC functions that support the implementation of asynchronous blocks. Some functions are specifically designed for use in asynchronous blocks. For example, LibSetAsyncCounter generates a call to update a timer for an asynchronous block. Other functions are utilities that return information required by asynchronous blocks (for example, information about connected function call subsystems).

The following table summarizes the public calls in the library. For details, see the library source code and the vxinterrupt1.tlc andvxtask1.tlc files, which call the library functions.

Summary of asynclib.tlc Library Functions

Function Description
LibBlockExecuteFcnCall For use by inlined S-functions with function call outputs. Generates code to execute a function call subsystem.
LibGetBlockAttribute Returns a field value from a block record.
LibGetFcnCallBlock Given an S-Function block and call index, returns the block record for the downstream function call subsystem block.
LibGetCallerClockTickCounter Provides access to the time counter of an upstream asynchronous task.
LibGetCallerClockTickCounterHighWord Provides access to the high word of the time counter of an upstream asynchronous task.
LibManageAsyncCounter Determines whether an asynchronous task needs a counter and manages its own timer.
LibNeedAsyncCounter If the calling block requires an asynchronous counter, returnsTLC_TRUE, otherwise returnsTLC_FALSE.
LibSetAsyncClockTicks Returns code that sets clockTick counters that are to be maintained by the asynchronous task.
LibSetAsyncCounter Generates code to set the tick value of the block's asynchronous counter.
LibSetAsyncCounterHighWord Generates code to set the tick value of the high word of the block's asynchronous counter

See Also

Topics