割込みシミュレーション
割込みハンドラの追加
アプリケーションの概要
ARM7TDMI用の割込みハンドラの記述
Cortex-M3用割込みハンドラの記述
プロジェクトの設定
シミュレーション環境の設定
C-SPYセットアップマクロファイルの定義
C-SPYオプションの設定
プロジェクトのビルド
シミュレータの起動
割込みシミュレーションの指定
イミディエイトブレークポイントの設定
割込みシミュレーション
アプリケーションの実行
マクロによる割込みとブレークポイントの設定
このチュートリアルでは、シリアルポートの割込みハンドラをプロジェクトに追加します。フィボナッチ数列をオンチップ通信周辺デバイスからリードします(UART)。
このチュートリアルでは、ARM7TDMIとCortex-M3に割込み関数を記述する方法を説明します。また、割込み、ブレークポイント、マクロをサポートする機能を使用して、割込みをシミュレーションする方法を示します。この例では、シミュレーションの細かい説明は省かれていることに注意してください。ここでの目的は、C-SPY®のマクロ、ブレークポイント、割込みシステムを使用して、ハードウェアをシミュレーションできる状況を示すことです。
このチュートリアルでは、これまでに説明されているIAR Embedded Workbench® IDEの基本事項について習熟していることを前提としています。
割込みシミュレーションを実行するには、IAR C-SPYシミュレータを使用する必要があることに注意してください。
割込みハンドラの追加
このセクションでは、割込みを簡単に記述する方法を示します。まずこのプロジェクトで使用するアプリケーションについて簡単に説明した後で、プロジェクトの設定方法について説明します。
アプリケーションの概要
割込みハンドラは、シリアル通信ポート受信レジスタ (UART)、UARTRECEIVEから値を読み取ります。そして、その値を出力します。メインプログラムでは割込みを有効にして、割込みを待機しながら、フォアグラウンドプロセスでピリオド(.)の出力を開始します。
Note: このチュートリアルでは、UARTRECEIVEは、それぞれARM7TDMIベースのダミーデバイスarm7およびCortex-M3ベースのダミーデバイスcm3上の受信レジスタを指します。このチュートリアルに従ってC-SPYシミュレータで割込みをシミュレーションするには、使用するコアとデバイスに適したレジスタを使用する必要があります。
ARM7TDMI用の割込みハンドラの記述
以下の行は、このチュートリアルで使用されている割込みハンドラの定義です(ソースコード全体については、 \tutorディレクトリにあるproject4のファイルarm Interrupt.cを参照)。
/* IRQハンドラを定義します */
__irq __arm void IRQ_Handler(void)
__irqキーワードを使用して、割込み関数に必要な呼出し規約を使用するようにコンパイラに指示します。__armキーワードを使用して、IRQハンドラがARMモードで確実にコンパイルするようにします。この例では、UART 受信割込みだけを使用しますので、割込みソースを確認する必要がありません。ただし、一般的には数個の割込みソースを使用する場合、アクション実行前に割込みサービスルーチンで割込みソースを確認する必要があります。
本チュートリアルで使用する拡張キーワードについては、『ARM®用IAR C/C++開発ガイド』を参照してください。
Cortex-M3用の割込みハンドラの記述
Cortex-M3では、割込みサービスルーチンの入力とリターンは、通常の関数と同じです。つまり、特殊なキーワードは必要ありません。
Project4CM3Interrupt.cファイルには、割込み関数UART_Handlerが用意されています。Cortex-Mデバイス用の割込み関数を追加すると、割込みベクタテーブルにもその関数名を追加する必要があります。これは、システム起動コードcstartup.s.で行います。このチュートリアルでは、UART_Handler関数への参照は__vector_tableにすでに用意されており、これはファイルCstartupCM3.sにあります。
Cortex-Mのデバイス固有の割込み関数を記述する方法については、ARM®用IAR C/C++開発ガイドを参照してください。
プロジェクトの設定
1
前のチュートリアルで使用したワークスペースtutorialsに新しいプロジェクトを作成して、project4と名前を付けます。
2
Utilities.cInterrupt.cの2つのファイルをプロジェクトに追加します。
3
[ワークスペース]ウィンドウでプロジェクトレベルノードを選択して、ロジェクト>オプションを選択します。一般オプションカテゴリを選択して、ターゲットタブをクリックします。コアドロップダウンリストで[ARM7TDMI]または[Cortex-M3]を選択します。
4
ARM7TDMIの場合は、C/C++ コンパイラカテゴリを選択して、コードタブをクリックします。インタワークコードを生成オプションを選択します。
5
また、出荷時設定がC/C++ コンパイラリンカのカテゴリで使用されているか確認してください。
次に、シミュレーション環境を設定します。
シミュレーション環境の設定
C-SPYの割込みシステムは、サイクルカウンタに基づいて動作します。C-SPYが割込みを生成するまでの経過サイクル数を指定できます。
UARTへの入力をシミュレーションするために、値をファイルInputData.txtからリードします。このファイルには、フィボナッチ数列が格納されています。UART受信レジスタUARTRECEIVEイミディエイト読込みブレークポイントを設定して、ユーザ定義マクロ関数を接続します(この例ではAccessマクロ関数)。このマクロは、テキストファイルからフィボナッチ数列をリードします。
割込みが生成され、割込みルーチンがUARTRECEIVEをリードし、ブレークポイントがトリガされるたびにAccessマクロ関数が実行されて、フィボナッチ数列がUART受信レジスタにライトされます。
プロセッサがUARTRECEIVEレジスタを読み込むに、イミディエイト読込みブレークポイントによってブレークがトリガされるので、マクロがレジスタに格納した値がすぐに命令によって読み込まれます。
このセクションでは、シリアルポートの割込みシミュレーションを行うためのシミュレータ設定に関連して実行する手順を示します。以下の手順があります。
*
C-SPYセットアップファイルの定義(ファイルInputData.txtを開いてAccessマクロ関数を定義)
*
*
*
*
*
ブレークポイントの設定とAccessマクロ関数の関連付け
Note: システムタイマ割込みシミュレーションの簡単な例については、 『C-SPY® ARM®用デバッグガイド』を参照してください。
C-SPYセットアップマクロファイルの定義
C-SPYでは、C-SPY起動シーケンス中に登録されるセットアップマクロを定義できます。このチュートリアルでは、arm\tutorディレクトリにあるC-SPYマクロファイルSetupSimple.macを使用します。このファイルの構造は以下のとおりです。
最初に、セットアップマクロ関数execUserSetupが定義されています。このマクロ関数は、C-SPYの設定中に自動的に実行されます。そのため、この関数を使用して、シミュレーション環境を自動設定します。このマクロが実行されたことを示すメッセージが[ログ]ウィンドウに出力されます。
execUserSetup()
{
__message "execUserSetup() called\n";
次に、ファイルInputData.txtを開きます。このファイルには、UARTに格納するフィボナッチ数列が記述されています。
_fileHandle = __openFile( "$PROJ_DIR$\\InputData.txt", "r" );
その次に、マクロ関数Accessが定義されています。このマクロ関数は、ファイルInputData.txtからフィボナッチ数列を読み込んで、受信レジスタアドレスに代入します。
Access()
{
__message "Access() called\n";
__var _fibValue;
if( 0 == __readFile( _fileHandle, &_fibValue ) )
{
UARTRECEIVE = _fibValue;
}
}
Accessマクロは、イミディエイト読込みブレークポイントに接続する必要があります。ただし、このチュートリアルでは、後半部分でその接続を行います。
これで、このファイルには、リセット時と終了時のファイルハンドリングを適切に管理するための2つのマクロ関数が記述されています。
マクロの詳細については、『C-SPY® ARM®用デバッグガイド』を参照してください。
次に、マクロファイルを指定して、その他の必要なデバッガオプションを設定します。
C-SPYオプションの設定
1
デバッガオプションを設定するには、プロジェクト>オプションを選択します。デバッガカテゴリで、設定タブをクリックします。
2
マクロファイルの使用参照ボタンを使用して、使用するマクロファイルを指定します。
SetupSimple.mac
別の方法として、引数変数を使用してパスを指定することもできます。
$PROJ_DIR$\SetupSimple.mac
引数変数のリファレンス情報は、『 ARM®用IDEプロジェクト管理およびビルドガイド』を参照してください。
3
次にデバイス記述ファイルを指定します。このファイルを使用すると、[レジスタ]ウィンドウでUARTRECEIVEを表示することができ、割込みシステムで必要な割り込み定義が入手できます。
ARM7TDMIの場合、デバイス記述ファイルオプションを[$TOOLKIT_DIR$\tutor\config\ioarm7.ddf]に設定します。
Cortex-M3の場合、デバイス記述ファイルオプションを[$TOOLKIT_DIR$\tutor\config\iocm3.ddf]に設定します。
4
[Run to main]を選択して、[OK]をクリックします。これにより、main関数まで実行するとデバッグセッションが開始されるように設定されます。
これで、プロジェクトをビルドする準備ができました。
プロジェクトのビルド
1
プロジェクト>作成を選択して、プロジェクトをコンパイルして、リンクします。
別の方法として、ツールバーの作成ボタンをクリックすることもできます。作成コマンドは、変更されたファイルをコンパイルして、リンクします。
シミュレータの起動
1
ダウンロードしてデバッグボタンをクリックして、C-SPYを起動し、project4またはproject4CM3プロジェクトを実行します。
いくつかウィンドウが開く中で、[Interrupt.c]ウィンドウが表示されます。このウィンドウをクリックして、アクティブウィンドウにします。
2
[ログ]ウィンドウを調べます。マクロファイルがロードされ、execUserSetup関数が呼び出されたことを確認します。
割込みシミュレーションの指定
ここで、2000サイクルごとの割込みをシミュレーションするように割込みを指定します。
1
シミュレータ>割込み設定を選択して、割込み設定ダイアログボックスを表示します。新規作成をクリックして割込みの編集ダイアログボックスを開きます。
割込みに以下の設定を行います。
 
シミュレータが割込みを正しくシミュレーションするために使用する割込み定義
シミュレータを実行してから最初に割込みを有効にするまでの待機時間を指定。サイクルカウンタがこの値に達すると、割込みが有効になります。
確率を指定します。(100%を指定すると割込みが指定された頻度で発生。別のパーセント値を指定すると、割込み動作をよりランダムにシミュレーション可能。
C-SPYを実行すると、サイクルカウンタが初回割込み待機時間に到達するまで待機します。最初のアセンブラ命令が実行されると、その後は約2000サイクルごとに割込みが繰り返し発生します。
2
設定を指定したら、[OK]をクリックして割込みの編集ダイアログボックスを閉じます。もう一度[OK]をクリックして、割込み設定ダイアログボックスを閉じます。
イミディエイトブレークポイントの設定
マクロを定義してイミディエイトブレークポイントに接続することによって、マクロを使用してハードウェアデバイス、たとえばこのチュートリアルのように入出力ポートの動作をシミュレーションできます。イミディエイトブレークポイントでは実行を停止するわけではありません。一時的にシミュレーションの実行を停止して、条件のチェックを行い、接続されているマクロを実行するだけです。
この例では、UARTRECEIVEアドレスにイミディエイト読込みブレークポイントを設定して、定義済みのAccessマクロをそこに接続することによって、UARTへの入力をシミュレーションします。マクロによりUARTへの入力をシミュレーションします。以下の手順に従います。
1
表示>ブレークポイントを選択して[ブレークポイント]ウィンドウを開き、右クリックしてコンテキストメニューを開きます。そこから新規ブレークポイント>イミディエイトを選択してイミディエイトタブを開きます。
2
C-SPYは実行中にUARTRECEIVEアドレスからの読込みアクセスを検出すると、一時的にシミュレーションの実行を停止して、Accessマクロを実行します。マクロはファイルInputData.txtから値をリードし、UARTRECEIVEにライトします。C-SPYがシミュレーションを再開して、UARTRECEIVEの受信バッファ値をリードします。
3
[OK]をクリックして、[ブレークポイント]ダイアログボックスを閉じます。
割込みシミュレーション
このセクションでは、アプリケーションを実行して、シリアルポートの割込みシミュレーションを行います。
アプリケーションの実行
1
[Interrupt.c]ソースウィンドウで、アプリケーションをステップ実行して、whileループに到達したら停止します。このループで、アプリケーションは入力を待機します。
2
[Interrupt.c]ソースウィンドウで、関数IRQ_Handler またはUART_Handlerを探します。
3
この関数の++callCount;文に挿入ポイントを設定した後、編集>ブレークポイントの切替えを選択するか、ツールバーのブレークポイントの切替えボタンをクリックして、ブレークポイントを設定します。その他に、コンテキストメニューから同じ操作を実行することもできます。
ブレークポイントの詳細を検証する場合、表示>ブレークポイントを選択します。
4
[ターミナルI/O]ウィンドウを開いて、デバッグ>実行を選択するか、ツールバーの実行ボタンをクリックして、アプリケーションを実行します。
アプリケーションは割込み関数の位置で停止します。
5
シリアル通信ポートの受信レジスタUARTRECEIVEの内容を調べるには、>レジスタを選択して[レジスタ]ウィンドウを開きます。ドロップダウンリストで[UART]を選択します。
6
アプリケーションを実行するには、デバッグ>実行を選択するか、ツールバーの実行ボタンをクリックします。アプリケーションは割込み関数の位置で停止します。
UARTRECEIVEの内容がどのようにして更新されたかに注目してください。
7
もう一度実行をクリックすると、次の数字が[ターミナルI/O]ウィンドウに出力されます。
メインプログラムでフィボナッチ値のカウンタに上限を設定しているので、チュートリアルアプリケーションはすぐにexitラベルに到達し、停止します。
[ターミナルI/O]ウィンドウにフィボナッチ数列が表示されます。
マクロによる割込みとブレークポイントの設定
ブレークポイントの設定や割込みを定義する手順を自動化するには、それぞれシステムマクロ__setSimBreak__orderInterruptをセットアップマクロexecUserSetupで実行します。
ARM7TDMI用のファイルSetupAdvanced.macとCortex-M3用のSetupAdvancedCM3.macは、ブレークポイントの設定および割込みを指定するためにシステムマクロによって拡張されます。
ARM7TDMI(arm7ダミーデバイス)の場合:
simulationSetup()
{...
_interruptID = __orderInterrupt( "IRQ", 4000,
2000, 0, 1, 0, 100 );
 
if( -1 == _interruptID )
{
__message "ERROR: failed to order interrupt";
}
 
_breakID = __setSimBreak( "UARTRECEIVE", "R", "Access()" );
}
Cortex-M3(cm3ダミーデバイスの場合):
simulationSetup()
{...
_interruptID = _ _orderInterrupt( "UART", 4000,
2000, 0, 1, 0, 100 );
 
if( -1 == _interruptID )
{
__message "ERROR: failed to order interrupt";
}
 
_breakID = __setSimBreak( "UARTRECEIVE", "R", "Access()" );
}
前のチュートリアルで使用したファイルSetupSimple.macをファイルSetupAdvanced.macまたはSetupAdvancedCM3.macで置き換えることによって、ブレークポイントの設定と割込みの定義が、C-SPYの起動時に自動的に実行されます。したがって、シミュレーションを開始するときに、割込ダイアログボックスとブレークポイントダイアログボックスに値を手動で入力する必要はありません。
Note: ファイルSetupAdvanced.macまたはSetupAdvancedCM3.macをロードするには、その前に定義されていたブレークポイントと割込みを削除する必要があります。