Top -> FreeRtos -> designtips4.html | ||||||||||||
ソリューション #4 プロセッサオーバーヘッドを減らします |
||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
<<< | >>> | ||||||||||||
ノート:このページは FreeRTOS V4.0.0 の導入以降更新されてません。 V4.0.0 は斬新なソリューションの提供であるコルーチンのコンセプトを紹介します。 タスクとコルーチンのドキュメンテーションは多くのインフォメーションを提供する。 |
||||||||||||
概 要 | ||||||||||||
ソリューション # 2 で、RTOS 機能を完全に利用することによって、クリーンなアプリケーションがどのように生産されることができるか示しました。
ソリューション # 3が限定された RAM リソースを持っている組み込みコンピュータのためにこれがどのように改変されるのかを示しました。 ソリューション # 4が RTOS 処理オーバーヘッドの軽減の目的で更なる修正を試みた。ハイブリッド・スケジューリング・アルゴリズム(完全なプリエンティブでもなく完全な協調的でもない)が、協調的なスケジューリングのために、カーネルの構成を設定することによって作成され、イベント割り込みサービスルーチンの中からコンテキストスイッチを実行します。 以前、タイミングは vTaskDelayUntil () API 関数を使って実行されました。 プリエンティブなスケジューラーが使われたとき、コントロールタスクに最高優先順位を割り当てることは、正確に指定された時に実行し始めることを保証しました。 今協調的なスケジューラーが使われています − そのため、アプリケーションソースコードから明示的に求められるときのみタスクスイッチは起こるので − 保証されたタイミングは失われる。 ソリューション # 4が周辺機器タイマからのコンテキストスイッチが、コントロールタスクによって必要とされる正確な周波数によって、割り込みを保証するために使います スケジューラーは、実行可能な最高優先順位タスクにコンテキストスイッチで切り替える、ことを保証します。同じくキーパッドを走査している関数は通常のプロセッサ時間を必要とし、タイマ割り込みによってトリガーされたタスクで実行する。 |
||||||||||||
実 装 | ||||||||||||
ソリューション # 4機能タスクと優先度 |
||||||||||||
クリティカルなプラントコントロール機能は高優度タスクによって実行されます、しかし協調的なスケジューラーの使用はその実装に変更を必要とします。
このタスクのタイミングは容易に評価されることができます; 制御関数の最も悪いケース処理時間はエラー状態によって与えられます。例えば、ネットワーク・センサからのデータが間に合わないとき制御関数がタイムアウトする。 関数を走査しているキーパッドの実行時間は基本的に固定されています。 この方法での機能のチェイニングは必ずコントロール・サイクル周波数でジッターを生じる - あるいはもっと悪くコントロールサイクルミスする。 RS232 タスクは RS232 割り込みサービスルーチンによってスケジュールされる。 LEDの機能が持つフレキシブルなタイミング条件は、この機能をアイドル・タスク・フックの中で組み込みWeb サーバタスクと一緒にすることができる。 もしこれが適切ではないなら、高優先順位タスクに移動する。 |
||||||||||||
オペレーションのコンセプト | ||||||||||||
協調的スケジューラは明示的に要求された時のみコンテキストスイッチを実行します。 これはRTOS によって発生するプロセッサオーバーヘッドを大幅に減らします。アイドル・タスクは、組み込みの Web サーバ機能を含めて、カーネルからの不必要な割込みなしで実行します。 RS232 あるいは周辺機器のタイマからの割り込みが、必要なときだけコンテキストスイッチを起こす。 このように RS232 タスクはアイドル・タスクをプリエンティブするでしょう、そして、それ自身プラントコントロールタスクによってプリエンティブされることになる −優先度を付けられたシステム機能を維持しながら。 |
||||||||||||
スケジューラコンフィギュレーション | ||||||||||||
スケジューラーは協調的なオペレーション用に設定される。 カーネル時計はリアルタイムチック値のみを使用します。 | ||||||||||||
評 価 | ||||||||||||
|
||||||||||||
結 論 | ||||||||||||
RTOS カーネルの特徴は、プロセッサと記憶制約条件が完全なプリエンティブ解決法を妨げるシステムでさえ、単純化されたデザインと極めて少さなオーバーヘッドを可能にする。 | ||||||||||||
|
||||||||||||
例 | ||||||||||||
この例は前に提示した例題のアプリケーションの部分的な実装です。 FreeRTOS API を使用する。 | ||||||||||||
高優先順度タスク | ||||||||||||
void vTimerInterrupt( void ) { // 'Give' the semaphore. This will wake the high priority task. xSemaphoreGiveFromISR( xTimingSemaphore ); // The high priority task will now be able to execute but as // the cooperative scheduler is being used it will not start // to execute until we explicitly cause a context switch. taskYIELD(); }ISR の中からコンテキストスイッチを強制するために使われるシンタックスが異なるポートでは異なることに注意。 直接この例をまねないでください、その代わりに、あなたが使っているポートがないかドキュメンテーションをチェックしてください。 高優先順位タスクはプラントコントロールとキーパッド機能の両方を含んでいます。 高優先順位タスクはプラントコントロールとキーパッド機能性両方を含んでいます。 PlantControlCycle () は整合性を保つため、最初にそのタイミングで呼ばれます。 |
||||||||||||
void HighPriorityTaskTask( void *pvParameters ) { // Start by obtaining the semaphore. xSemaphoreTake( xSemaphore, DONT_BLOCK ); for( ;; ) { // Another call to take the semaphore will now fail until // the timer interrupt has called xSemaphoreGiveFromISR(). // We use a very long block time as the timing is controlled // by the frequency of the timer. if( xSemaphoreTake( xSemaphore, VERY_LONG_TIME ) == pdTRUE ) { // We unblocked because the semaphore became available. // It must be time to execute the control algorithm. PlantControlCycle(); // Followed by the keyscan. if( KeyPressed( &Key ) ) { UpdateDisplay( Key ); } } // Now we go back and block again until the next timer interrupt. } } |
||||||||||||
RS232 タスク | ||||||||||||
RS232 タスクはブロック状態で待ち行列の上にデータが到着するのを待ちます。 RS232 割り込みサービスルーチンは待ち行列にデータをポストしなくてはならないので − タスクを実行準備状態とする − そして強制的にコンテキストスイッチを起こす。このメカニズムは上記タイマ割り込み擬似コードに従う。 従って RS232 タスクは次の擬似コードによって表されることができます: void vRS232Task( void *pvParameters ) { DataType Data; for( ;; ) { if( cQueueReceive( xRS232Queue, &Data, MAX_DELAY ) ) { ProcessRS232Data( Data ); } } } |
||||||||||||
組み込みの Web サーバと LED 機能 | ||||||||||||
残っているシステム機能はアイドル・タスク・フックの中に置きます。 これはただアイドル・タスクのそれ各サイクルで呼び出される関数です。
void IdleTaskHook( void ) { static portTickType LastFlashTime = 0; ProcessHTTPRequests(); // Check the tick count value to see if it is time to flash the LED // again. if( ( xTaskGetTickCount() - LastFlashTime ) > FLASH_RATE ) { UpdateLED(); // Remember the time now so we know when the next flash is due. LastFlashTime = xTaskGetTickCount(); } } |
||||||||||||
|
||||||||||||
More Advanced | ||||||||||||
Top に戻る | ||||||||||||