Real-Time Workshop User's Guide    

非インラインS-Functionデバイスドライバの作成

概要

デバイスドライバS-Functionは、2,3の操作しか行わないので、比較的実現が容易です。それらの操作は以下の通りです。

ドライバは、S-Function APIが要求する固有の関数を実現することによって、これらの操作を行います。

これらの関数は、ソースファイルに対してプライベートなので、複数の同じS-Functionをモデルに組み込むことができます。そのような非インラインS-Functionは、SimStructを例示します。

Simulinkとリアルタイムに対する条件付きのコンパイル

非インラインS-Functionは、Simulinkとリアルタイム環境の両方で機能しなければなりません。Real-Time Workshopは、プリプロセッサシンボルMATLAB_MEX_FILE, RTNRTを定義して、シミュレーションコードとリアルタイムコードを区別します。これらのシンボルは以下のように使います。

Real-Time Workshopは、これらの条件文を提供し、ドライバS-Functionが適切なときにのみハードウェアにアクセスすることを保証することを援助します。ターゲットI/Oハードウェアはシミュレーション中に現れないので、ターゲット環境内でのアドレスへの書き込みは、不正なメモリ参照、システムメモリの上書き、その他の深刻なエラーとなる場合があります。同様に、存在しないハードウェアレジスタからの読み込み操作は、モデル実行エラーを生じる場合があります。

つぎのコードでは、ハードウェアの初期化呼び出しが生成されたリアルルタイムコードでコンパイルされます。シミュレーション中に、MATLABコマンドウィンドウにメッセージが表示されます。

MATLAB_MEX_FILERTの条件文は、必要なインクルードファイルの制御も行います。下記の「必要な定義とインクルードファイル」を参照してください。

その他の手段でリアルタイムおよびシミュレーションコードの制御を行うほうがいい場合があります。例として、matlabroot/rtw/c/dos/devices/das16ad.cの変数ACCESS_HWの使用法を参照してください。

必要な定義とインクルードファイル

ドライバS-Functionは、つぎの3つのステートメントを、つぎの順で始めなければなりません。

  1. #define S_FUNCTION_NAME name

    これは、S-Functionコードのエントリポイント名を定義します。nameは、拡張子.cを除いたS-Functionソースファイル名でなければなりません。たとえば、S-Functionソースファイルがdas16ad.cの場合、

  1. #define S_FUNCTION_LEVEL 2

    このステートメントは、レベル2のS-Functionとしてファイルを定義します。これにより、S-Functionのすべての機能を利用することができます。レベル1のS-Functionは、現在は下位互換性を維持するためにのみ利用されます。

  1. #include "simstruc.h"

    ファイルsimstruc.hは、SimStruct(Simulinkデータ構造体) と関連するアクセスマクロを定義します。MATLAB MEX APIかmx*関数に対するアクセス方法も定義します。

S-Functionを、MEXファイルあるいはリアルタイムコードのどちらとしてビルドするかにより、S-Functionの終了時につぎのファイルのうちの1つをインクルードしなければなりません。

非インラインS-Functionは、sfuntmpl.cの下記のコードのように、条件付きでこれらのファイルを両方インクルードします。

必要な関数

S-Function APIでは、ドライバ内で複数の関数を実現する必要があります。

上記に加えて、mdlStart関数を実現したい場合があります。mdlStartは、モデル実行の開始時に1回呼び出され、I/Oハードウェアを希望する初期状態に設定するような操作に対して役立ちます。

つぎの節では、これらの関数の実現のためのガイドラインを説明します。

mdlInitializeSizes

この関数では、SimStructの様々なパラメータのサイズを指定します。この情報は、S-Functionに渡されるパラメータにより異なります。「ドライバのパラメータ化」では、S-Functionダイアログボックスで指定されたパラメータ値にアクセスする方法を説明しています。

サイズの初期化- 入力デバイス.    mdlInitializeSizes関数は、SimStructのサイズ情報を設定します。mdlInitializeSizesの下記の実現は、典型的なADCドライバブロックを初期化します。

このルーチンは、最初に入力パラメータ数がブロックのダイアログボックス内のパラメータ数と等しいことを検証しています。つぎに、ダイアログからNumber of Channelsパラメータを取得します。

ADCはソースブロックで出力のみをもつので、ssSetNumInputPortsは、入力端子数を0に設定します。

ssSetNumOutputPortsは、出力端子数を、ダイアログボックスから取得したI/Oチャンネル数と等しく設定します。

ssSetNumSampleTimesは、サンプル時間数を1に設定します。これは、すべてのADCチャンネルが同じレートで実行される場合です。実際のサンプル間隔は、mdlInitializeSampleTimesで設定されます。

デフォルトでは、ADCブロックな直接フィードスルーをもちません。ADC 出力は、他のブロックから得られたデータではなく、ハードウェアから読み込まれた値を基に計算されます。

サイズの初期化 - 出力デバイス.   DACのような出力デバイスに対するサイズ情報の初期化は、ADCのサイズの初期化とはいくつかの重要な点で異なります。

つぎの例は、DACドライバブロックに対するmdlInitializeSizesの実現です。

mdlInitializeSampleTimes

デバイスドライバブロックは、離散ブロックで、サンプル時間を設定する必要があります。サンプル時間の設定の手順は、入力および出力デバイスドライバに対して同じです。すべてのデバイスのチャンネルが同じレートで実行されると仮定すると、S-Functionはサンプル時間を1つだけもちます。

mdlInitializeSampleTimesの以下の実現は、サンプル時間をブロックのダイアログボックスから読み込みます。この場合、サンプル時間はダイアログボックス5番目のパラメータです。サンプル時間のオフセットは0に設定されます。

mdlStart

mdlStartは、オプション関数です。モデル実行の開始時に1回呼び出され、ハードウェアを初期化するために利用します。ハードウェアにアクセスするため、この例のように、リアルタイムコードまたはシミュレーション用に条件付きでコンパイルします。

mdlOutputs

デバイスドライバブロックの基本的な目的は、プログラムとI/Oハードウェアとの通信を行うことです。一般的に、これはコンパイラのCライブラリの一部である低レベルのハードウェア呼び出し、あるいはI/Oハードウェアに付属するCの呼び出し可能な関数を使って行われます。

すべてのS-Functionは、mdlOutputs関数を実現して、ブロック出力を計算します。デバイスドライバブロックに対して、mdlOutputsは、ハードウェアから読み込んだり、ハードウェアへ書き込むコードを含みます。

mdlOutputs - 入力デバイス。   入力デバイス用のドライバ(ADC)のようなでは、mdlOutputsは、以下を行う必要があります。

つぎのコードは、ADCドライバmatlabroot/rtw/c/dos/devices/das16ad.cmdlOutputs関数です。関数は、matlabroot/rtw/c/dos/devices/das16ad.hで定義されたマクロを使って、低レベルのハードウェアのアクセスを行います。Boolean変数ACCESS_HW(条件付きのコンパイル以外)は、シミュレーションとリアルタイムコードの実行を制御します。リアルタイムコードは、ハードウェアから値を読み込み、それらを出力ベクトルに格納します。シミュレーションコードは、単純にすべてのチャンネルにおいて0を出力します。

mdlOutputs - 出力デバイス.   (DACのような)出力デバイス用のドライバでは、mdlOutputsは以下を行う必要があります。

つぎのコードは、DACドライバmatlabroot/rtw/c/dos/devices/das16da.cmdlOutputs関数です。関数は、matlabroot/rtw/c/dos/devices/das16ad.hで定義されたマクロを使って、低レベルのハードウェアアクセスを行います。この関数は、すべてのチャンネルにわたって、ブロックの入力値の取得とスケーリングを繰り返します。その後範囲チェックと(必要ならば) 各値のトリミングを行います。最後に、値をハードウェアに書き出します。

シミュレーションでは、この関数はスタブです。

mdlTerminate

この最後に必要な関数は、一般にDACドライバでのみ必要です。つぎのルーチンは、各DACチャンネルの出力を0に設定します。

ADCドライバは、通常mdlTerminateを空のスタブとして実現します。


 ドライバのパラメータ化 インラインS-Functionデバイスドライバの作成