セマフォ:紹介と基本的なサービス
RTOSRevealedシリーズを表示する
セマフォは以前の記事で紹介されました。それらの主な用途は、リソースへのアクセスの制御です。
セマフォの使用
Nucleus SEでは、セマフォはビルド時に構成されます。アプリケーションには、最大16個のセマフォが構成されている場合があります。セマフォが構成されていない場合、セマフォに関連するデータ構造やサービス呼び出しコードはアプリケーションに含まれません。
セマフォは、単にタイプ U8 のカウンターです。 、複数のタスクで安全に利用できるようにアクセスが制御されます。タスクは、セマフォをデクリメント(取得)し、インクリメント(リリース)することができます。値がゼロのセマフォを取得しようとすると、API呼び出しとNucleus SE構成で選択されたオプションによっては、エラーまたはタスクの中断が発生する可能性があります。
セマフォの設定
セマフォの数
Nucleus SEのほとんどの側面と同様に、セマフォの構成は主に# define によって制御されます。 nuse_config.h のステートメント 。キー設定は NUSE_SEMAPHORE_NUMBER です。 、アプリケーションに設定されているセマフォの数を決定します。デフォルト設定は0(つまり、セマフォは使用されていません)で、16までの任意の値に設定できます。値が間違っていると、コンパイル時エラーが発生し、 nuse_config_check.h <でのテストによって生成されます。 / strong> (これは nuse_config.c に含まれています したがって、このモジュールでコンパイルされます)結果として#エラー コンパイル中のステートメント。
ゼロ以外の値を選択することは、セマフォの「マスターイネーブル」です。これにより、一部のデータ構造がそれに応じて定義およびサイズ設定されます。これについては、この記事の後半で詳しく説明します。また、APIを有効にする設定をアクティブにします。
APIの有効化
Nucleus SEのすべてのAPI関数(サービス呼び出し)には、有効な#定義があります nuse_config.h の記号 。セマフォの場合、これらは次のとおりです。
NUSE_SEMAPHORE_OBTAIN
NUSE_SEMAPHORE_RELEASE
NUSE_SEMAPHORE_RESET
NUSE_SEMAPHORE_INFORMATION
NUSE_SEMAPHORE_COUNT
デフォルトでは、これらはすべて FALSE に設定されています 、したがって、各サービスコールを無効にし、実装コードを含めることを禁止します。アプリケーションのセマフォを構成するには、使用するAPI呼び出しを選択し、それらの有効化記号を TRUE に設定する必要があります。 。
これは、デフォルトの nuse_config.h からの抜粋です。 ファイル。
#define NUSE_SEMAPHORE_NUMBER 0 / *システム内のセマフォの数-0-16 * /#define NUSE_SEMAPHORE_OBTAIN FALSE / *サービス呼び出しイネーブラー* /#define NUSE_SEMAPHORE_RELEASE FALSE / *サービス呼び出しイネーブラー* /#define NUSE_SEMAPHORE_RESET FALSE / *コールイネーブラー* /#define NUSE_SEMAPHORE_INFORMATION FALSE / *サービスコールイネーブラー* /#define NUSE_SEMAPHORE_COUNT FALSE / *サービスコールイネーブラー* /
セマフォAPI関数が有効で、セマフォが構成されていない場合( NUSE_Semaphore_Count()を除く)、コンパイル時エラーが発生します。 これは常に許可されています)。コードで有効にされていないAPI呼び出しを使用すると、アプリケーションに実装コードが含まれていないため、リンク時間エラーが発生します。
セマフォサービス呼び出し
Nucleus RTOSは、セマフォに関連する8つのサービス呼び出しをサポートしており、次の機能を提供します。
-
セマフォを取得します。 NUSE_Semaphore_Obtain()によって実装されます NucleusSEで。
-
セマフォを解放します。 NUSE_Semaphore_Release()によって実装されます NucleusSEで。
-
タスクを中断(リセット)せずに、セマフォを未使用の状態に復元します。 NUSE_Semaphore_Reset()によって実装されます NucleusSEで。
-
指定されたセマフォに関する情報を提供します。 NUSE_Semaphore_Information()によって実装されます NucleusSEで。
-
アプリケーションに(現在)構成されているセマフォの数を返します。 NUSE_Semaphore_Count()によって実装されます NucleusSEで。
-
アプリケーションに新しいセマフォを追加します(作成します)。 NucleusSEには実装されていません。
-
アプリケーションからセマフォを削除します(削除)。 NucleusSEには実装されていません。
-
アプリケーション内の(現在)すべてのセマフォへのポインターを返します。 NucleusSEには実装されていません。
これらの各サービス呼び出しの実装について詳しく調べます。
セマフォの取得と解放のサービス
セマフォで実行できる基本的な操作は、セマフォの取得(デクリメント)と解放(インクリメント)です。 NucleusRTOSとNucleusSEはそれぞれ、これらの操作のための2つの基本的なAPI呼び出しを提供します。これについては、ここで説明します。
セマフォの取得
セマフォを取得するためのNucleusRTOS API呼び出しは非常に柔軟性があり、操作をすぐに完了できない場合は、無期限に、またはタイムアウトで一時停止できます。つまり、現在値がゼロのセマフォを取得しようとします。 Nucleus SEは、タスクの一時停止がオプションであり、タイムアウトが実装されていないことを除いて、同じサービスを提供します。
セマフォを取得するためのNucleusRTOSAPI呼び出し
サービスコールプロトタイプ:
ステータスNU_Obtain_Semaphore(NU_SEMAPHORE *セマフォ、
UNSIGNED suspend);
パラメータ:
セマフォ –ユーザー提供のセマフォ制御ブロックへのポインター
一時停止 –タスクサスペンドの仕様。 NU_NO_SUSPEND の可能性があります または NU_SUSPEND またはタイムアウト値
返品:
NU_SUCCESS –通話は正常に完了しました
NU_UNAVAILABLE –セマフォの値はゼロでした
NU_INVALID_SEMAPHORE –セマフォポインタが無効です
NU_INVALID_SUSPEND –非タスクからサスペンドが試行されました
NU_SEMAPHORE_WAS_RESET –タスクが一時停止されている間にセマフォがリセットされました
セマフォを取得するためのNucleusSEAPI呼び出し
このAPI呼び出しは、Nucleus RTOSAPIの主要な機能をサポートしています。
サービスコールプロトタイプ:
STATUS NUSE_Semaphore_Obtain(NUSE_SEMAPHORE semaphore、
U8サスペンド);
パラメータ:
セマフォ –使用するセマフォのインデックス(ID)
一時停止 –タスクサスペンドの仕様。 NUSE_NO_SUSPEND の可能性があります または NUSE_SUSPEND
返品:
NUSE_SUCCESS –通話は正常に完了しました
NUSE_UNAVAILABLE –セマフォの値はゼロでした
NUSE_INVALID_SEMAPHORE –セマフォインデックスが無効です
NUSE_INVALID_SUSPEND –非タスクスレッドから、またはAPI呼び出しのブロックが有効になっていないときにサスペンドが試行されました
NUSE_SEMAPHORE_WAS_RESET –タスクが一時停止されている間にセマフォがリセットされました
セマフォの取得のNucleusSE実装</ strong>
NUSE_Semaphore_Obtain()のコードの大部分 API関数(パラメーターチェック後)は、API呼び出しのブロック(タスクの一時停止)のサポートが有効になっているかどうかに応じて、条件付きコンパイルによって選択されます。ここでは、2つのバリアントを別々に見ていきます。
ブロッキングが有効になっていない場合、このAPI呼び出しのロジックは非常に単純です。
if(NUSE_Semaphore_Counter [semaphore]!=0)/ *使用可能なセマフォ* / {NUSE_Semaphore_Counter [semaphore]-; return_value =NUSE_SUCCESS;} else / *セマフォは使用できません* / {return_value =NUSE_UNAVAILABLE;}
セマフォ値がテストされ、ゼロ以外の場合はデクリメントされます。
ブロッキングを有効にすると、ロジックがより複雑になります。
do {if(NUSE_Semaphore_Counter [semaphore]!=0)/ *使用可能なセマフォ* / {NUSE_Semaphore_Counter [semaphore]-; return_value =NUSE_SUCCESS; suspend =NUSE_NO_SUSPEND; } else / *セマフォは使用できません* / {if(suspend ==NUSE_NO_SUSPEND){return_value =NUSE_UNAVAILABLE; } else {/ *タスクをブロックする* / NUSE_Semaphore_Blocking_Count [semaphore] ++; NUSE_Suspend_Task(NUSE_Task_Active、semaphore <<4)| NUSE_SEMAPHORE_SUSPEND); return_value =NUSE_Task_Blocking_Return [NUSE_Task_Active]; if(return_value!=NUSE_SUCCESS){suspend =NUSE_NO_SUSPEND; }}}} while(suspend ==NUSE_SUSPEND);
コードの説明が役立つ場合があります:
コードは do…while で囲まれています ループ。パラメータが一時停止している間継続します 値は NUSE_SUSPEND 。
セマフォがゼロ以外の場合、デクリメントされます。 一時停止 変数は NUSE_NO_SUSPEND に設定されています API呼び出しは NUSE_SUCCESS で終了します 。
セマフォがゼロで一時停止の場合 NUSE_NO_SUSPEND に設定されています 、API呼び出しは NUSE_UNAVAILBLE で終了します 。サスペンドが NUSE_SUSPEND に設定されている場合 、タスクは一時停止されています。戻り時(つまり、タスクがウェイクアップされたとき)、戻り値が NUSE_SUCCESS の場合 、(セマフォのリセットではなく)セマフォが解放されたためにタスクがウェイクアップされたことを示します。コードは先頭にループバックします。
セマフォのリリース
セマフォをリリースするためのNucleusRTOSAPI呼び出しは非常に簡単です。セマフォがインクリメントされ、成功が報告されます。 Nucleus SEは、オーバーフローチェックが実行されることを除いて、同じサービスを提供します。
セマフォを解放するためのNucleusRTOSAPI呼び出し
サービスコールプロトタイプ:
STATUS NU_Release_Semaphore(NU_SEMAPHORE * semaphore);
パラメータ:
セマフォ –ユーザー提供のセマフォ制御ブロックへのポインター
返品:
NU_SUCCESS –通話は正常に完了しました
NU_INVALID_SEMAPHORE –セマフォポインタが無効です
セマフォを解放するためのNucleusSEAPI呼び出し
このAPI呼び出しは、Nucleus RTOSAPIの主要な機能をサポートしています。
サービスコールプロトタイプ:
STATUS NUSE_Semaphore_Release(NUSE_SEMAPHORE semaphore);
パラメータ:
セマフォ –リリースされるセマフォのインデックス(ID)
返品:
NUSE_SUCCESS –通話は正常に完了しました
NUSE_INVALID_SEMAPHORE –セマフォインデックスが無効です
NUSE_UNAVAILABLE –セマフォの値は255であり、インクリメントできません
リリースセマフォのNucleusSE実装</ strong>
NUSE_Semaphore_Release()の初期コード API関数(パラメータチェック後)は、タスクのブロックが有効かどうかに関係なく一般的です。セマフォの値がチェックされ、255未満の場合は、デクリメントされます。
API呼び出しのブロック(タスクの一時停止)のサポートが有効になっている場合は、条件付きコンパイルによって追加のコードが選択されます:
NUSE_CS_Enter(); if(NUSE_Semaphore_Counter [semaphore] <255){NUSE_Semaphore_Counter [semaphore] ++; return_value =NUSE_SUCCESS; #if NUSE_BLOCKING_ENABLE if(NUSE_Semaphore_Blocking_Count [semaphore]!=0){U8インデックス; / *タスクがブロックされているかどうかを確認します* / / *このセマフォで* / NUSE_Semaphore_Blocking_Count [semaphore]-; for(index =0; indexこのセマフォで中断されているタスクがある場合、最初のタスクがウェイクアップされます。
次の記事では、イベントフラググループに関連するいくつかの追加のAPI呼び出しと、関連するデータ構造について説明します。
Colin Wallsは、エレクトロニクス業界で30年以上の経験があり、主に組み込みソフトウェアに専念しています。カンファレンスやセミナーで頻繁にプレゼンターを務め、組み込みソフトウェアに関する多数の技術記事と2冊の本を執筆しているコリンは、Mentor Embedded [Mentor Graphics Embedded Software Division]の組み込みソフトウェア技術者であり、英国を拠点としています。彼の通常のブログはhttp://blogs.mentor.com/colinwallsにあります。彼には、colin_walls @ mentor.com宛ての電子メールで連絡することができます
埋め込み