| Top -> FreeRtos -> designtips2.html | ||||||||||||
| ソリューション # 2 完全にプリエンティブなシステム  | 
    ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| <<< | >>> | ||||||||||||
| 概 要 | ||||||||||||
| これは伝統的なプリエンプティブ多重タスクソリューションです。 これはメモリとプロセッサのオーバーヘッドに関係なく、RTOSのサービスをフルに活用できます。自立した必要機能に単純化した多数のタスクに分割する。 | ||||||||||||
| 実 装 | ||||||||||||
| システムの一部分として、単独であるいは特定のタイミング条件を持つ個別のタスクが作成される。 | ||||||||||||
 
      ソリューション # 2機能タスクと優先度  | 
    ||||||||||||
| 処理が必要なイベントが発生するまで、タスクはブロック状態にある。
      イベントは外部装置(キーが押される等)あるいは内部(タイマが時間)がある。 タイミング必要条件に応じて優先度タスクに割り当てられる。 タイミング必要条件がより厳しいタスクはより優先度を高くする。  | 
    ||||||||||||
| オペレーションのコンセプト | ||||||||||||
| RTOSは実行可能な(ブロックされていない)最高優先度タスクがプロセッサ時間を得るように保証する。
      もしより高い優先度タスクが実行可能になったなら、カーネルは直ちに実行中のタスクを中止する。 このスケジューリングはアプリケーションソースコードの中の構成やコマンドで明示的に記述されず、自動的に起こります。 しかしながら、タスクの適切な優先度の割り当てはアプリケーションデザイナーの責任です。 実行可能がタスクがないとき、アイドル・タスクが実行する。 アイドル・タスクはプロセッサをパワーセーブモードへ移行オプションを置きます。  | 
    ||||||||||||
| スケジューラ・コンフィギュレーション | ||||||||||||
| スケジューラーはプリエンティブなオペレーションを構成する。 カーネル・チック周波数は必要とされる時間精度を保証する最も遅い値に設定すべきです。 | ||||||||||||
| 評 価 Evaluation  | 
    ||||||||||||
      
  | 
    ||||||||||||
| 結 論 | ||||||||||||
| アプリケーションを分割し、タスクとそれぞれのタスクに優先度を割当てることは熟慮を必要とします。 | ||||||||||||
| 
       | 
    ||||||||||||
| 例 | ||||||||||||
| この例は前に紹介した例題アプリケーションの部分的な実装です。FreeRTOS API を使用します。 | ||||||||||||
| プラントコントロールタスク | ||||||||||||
このタスクはすべてのコントロール機能を実行します。これはクリティカルなタイミングがあり、従ってシステム内の最も高い優先度を与える:#define CYCLE_RATE_MS       10
#define MAX_COMMS_DELAY     2
void PlantControlTask( void *pvParameters )
{
portTickType xLastWakeTime;
DataType Data1, Data2;
    InitialiseTheQueue();
    // A
    xLastWakeTime = xTaskGetTickCount();
    // B
    for( ;; )
    {
        // C
        vTaskDelayUntil( &xLastWakeTime, CYCLE_RATE_MS );
        
        // Request data from the sensors.
        TransmitRequest();
        
        // D
        if( xQueueReceive( xFieldBusQueue, &Data1, MAX_COMMS_DELAY ) )
        {
            // E
            if( xQueueReceive( xFieldBusQueue, &Data2, MAX_COMMS_DELAY ) )
            {
                PerformControlAlgorithm();
                TransmitResults();                
            }
        } 
    }
    
    // Will never get here!
}
      上記のコード片のラベルを以下に参照のこと: | 
    ||||||||||||
      
  | 
    ||||||||||||
| 組み込み Web サーバタスク | ||||||||||||
| 組み込み Web サーバタスクは次の擬似コードによって表すことができます。
      これはデータがあるときだけプロセッサ時間を使用する、しかし処理の完了には比較的長時間を要するでしょう。
       プラントコントロール、 RS232 あるいはキーパッドのスキャニング等に対して、それ等のタスクを妨げないように低い優先度を与える。 void WebServerTask( void *pvParameters )
{
DataTypeA Data;
    for( ;; )
    {
        // Block until data arrives.  xEthernetQueue is filled by the
        // Ethernet interrupt service routine.
        if( xQueueReceive( xEthernetQueue, &Data, MAX_DELAY ) )
        {
            ProcessHTTPData( Data );
        }        
    }
} | 
    ||||||||||||
| RS232 インタフェース | ||||||||||||
これは組み込みWeb サーバタスクの構造に類似しています。
      プラントコントロールタスクのタイミングに影響を与えないように中位の優先度を与える。
void RS232Task( void *pvParameters )
{
DataTypeB Data;
    for( ;; )
    {
        // Block until data arrives.  xRS232Queue is filled by the
        // RS232 interrupt service routine.
        if( xQueueReceive( xRS232Queue, &Data, MAX_DELAY ) )
        {
            ProcessSerialCharacters( Data );
        }        
    }
} | 
    ||||||||||||
| キーパッドを走査しているタスク | ||||||||||||
| これは単純に周期的なタスクです。 タイミング条件が
      RS232 タスクに類似していることから、中間の優先度を与えられる。 サイクルタイムは指定された限界よりずっと速く定めています。 それはリクエスト後直ちにプロセッサ時間を得られないかもしれないし-また実行中はプラントコントロールタスクによってプリエンプトされるかも知れません。 #define DELAY_PERIOD 4
void KeyScanTask( void *pvParmeters )
{
char Key;
portTickType xLastWakeTime;
    xLastWakeTime = xTaskGetTickCount();
    for( ;; )
    {
        // Wait for the next cycle.
        vTaskDelayUntil( &xLastWakeTime, DELAY_PERIOD );
        
        // Scan the keyboard.
        if( KeyPressed( &Key ) )
        {
            UpdateDisplay( Key );
        }
    }
}
      もしシステム全体のタイミングで、これが最下位優先度タスクにできたなら、vTaskDelayUntil
      () の呼び出しは必要ない。 すべてのより高い優先度タスクがブロックされたときは、キー走査関数は連続実行する−
      アイドル・タスクに代わって。 | 
    ||||||||||||
| LED タスク | ||||||||||||
これはすべてのタスクの中で最も単純です。#define DELAY_PERIOD 1000
void LEDTask( void *pvParmeters )
{
portTickType xLastWakeTime;
    xLastWakeTime = xTaskGetTickCount();
    for( ;; )
    {
        // Wait for the next cycle.
        vTaskDelayUntil( &xLastWakeTime, DELAY_PERIOD );
        // Flash the appropriate LED.
        if( SystemIsHealthy() )
        {
            FlashLED( GREEN );
        }
        else
        {
            FlashLED( RED );
        }        
    }
} | 
    ||||||||||||
| 
       | 
    ||||||||||||
| NEXT >>> Solution #3: RAM 使用量の節約 | ||||||||||||
| Top に戻る | ||||||||||||