マイコン入門spacer ad
トップページに戻る(マイコン徹底入門:STM32で始めるARM/Cortex-M3組み込み開発)
「マイコン徹底入門」とは? |  「マイコン徹底入門」を読む |  ダウンロード |  掲示板 |  筆者の自己紹介


Previous: 5.1.4. バイナリセマフォを取る

Up: 5. 割込み処理

Next: 6. クリティカルセクション


マイコン徹底入門:RTOS編:フリーのリアルタイムOS活用法: 5. 割込み処理:

5.2. カウンティングセマフォ

サンプルプログラム

freertos_interrupt_counting_semaphore_tim4

 前項のバイナリセマフォは、セマフォが取り得る状態というのは、セマフォが有るか無いかのどちらかでした。カウンティングセマフォは、一つのセマフォの中に、複数個分のの実行許可を持つものです。

 例えばあなたがとある大学の学生寮に住んでいるとします。住んでいる学生の数は10人です。この学生寮には3台の共用の自転車が有ります。自転車を使うときには、寮の玄関に掛けてある鍵を取り、使い終わったらすぐに返すというルールになっています。自転車を使いたい学生は多いのですが、自転車が3台しか有りませんから、鍵を取った学生が自転車を使える、鍵をとれなかった学生は鍵が返されるまで待つということになります。この例での鍵置き場と鍵がカウンティングセマフォに相当します。つまり利用できる資源が一つではないが一定数以下しかない場合に、鍵置き場と鍵(カウンティングセマフォ)を利用して、資源を利用できる者を管理するという仕組みな訳です。

 マイコンの場合であれば、例えばSTM32のように、ADCが二つしかないが、多くのセンサが接続されていて、複数のタスクがADCを共用したい場合に、カウンティングセマフォを利用すれば、それぞれのタスクに資源配分を管理できるようになります。

 カウンティングセマフォを利用する場合には、前項と同じように、プログラムの冒頭でセマフォのハンドラを定義しておきます。ハンドラの型はxSemaphoreHandleで同じです。

static xSemaphoreHandle xCountingSemaphore;

 次にxSemaphoreCreateCounting関数を使用してカウンティングセマフォを実際に作成します。xSemaphoreCreateCountingも実際にはマクロですがここでは関数として説明します。

関数名

xSemaphoreCreateCounting関数

関数プロトタイプ

xSemaphoreHandle xSemaphoreCreateCounting

? (

??? unsigned portBASE_TYPE uxMaxCount,

??? unsigned portBASE_TYPE uxInitialCount

? )

動作

カウンティングセマフォを作成します。

引数

uxMaxCount

作成するカウンティングセマフォで与えることのできるセマフォの最大数を指定します。

uxInitialCount

セマフォ作成時の初期状態ですでに与えられているセマフォの数を指定します。

戻り値

セマフォのハンドラ。セマフォを作成できなかったときはNULLを返します。

 サンプルプログラムでは以下のようにして、最大の容量が10のセマフォを作成しています。

xCountingSemaphore = xSemaphoreCreateCounting(10,0);

 これまでと同じように、セマフォが作成できない場合を想定して、対応するルーチンを記載しておきましょう。サンプルプログラムでは、セマフォがNULLで無い場合のみ、スケジューラを開始し、NULLであった場合にはエラーメッセージを表示させています。

if( xCountingSemaphore != NULL )

? {

??? xTaskCreate(vHandlerTask, (signed portCHAR *)"HandlerTask", 192, NULL, 3, NULL);

??? vTaskStartScheduler();

? }

else

? {

??? cprintf("Failed to create semaphore.\r\n");

? }

 カウンティングセマフォにセマフォを与えるには、バイナリセマフォの場合と同様xSemaphoreGiveFromISR関数を使用します。サンプルプログラムは長いので引用しませんが、要は、1000ms毎に3つのカウンティングセマフォを与えるルーチンになっています。各1000msの期間の開始時から50ms100ms150msが経過する時点で、セマフォを与えています。なおカウンティングセマフォに入っているセマフォの数をカウントするため、セマフォを与える度にsemaphore_counter変数をインクリメントしています。

 カウンティングセマフォからセマフォを取るには、バイナリセマフォと同様、xSemaphoreTake関数を使用します。

 サンプルプログラムでは以下のようにして、200ms毎にセマフォを取っています。

while(1)

? {

??? // Take semaphore to wait for interrupt

??? xSemaphoreTake (xCountingSemaphore, portMAX_DELAY);

?? ?//Print message through COM

??? delay_ms(200);

??? semaphore_counter--;

 

??? cprintf("Handler took semaphore.\r\n");

??? Print_Decimal(semaphore_counter);

??? cprintf(" semaphore pending.\r\n");

? }

 サンプルプログラムでは、周期中、0msから150msまでの間に、セマフォが連続して与えられます。この時点でセマフォの数は3つです。その後200ms毎にセマフォを取っているので、600ms経過して、3回セマフォを取った時点でセマフォが0になっています。200ms毎に実行されているので1秒間に5回実行されそうですが、4回目の時点では取るセマフォが無いので、Blocked状態になります。

Tick.

0 semaphore pending.

ISR gave semaphore.

1 semaphore pending.

ISR gave semaphore.

2 semaphore pending.

ISR gave semaphore.

3 semaphore pending.

Handler took semaphore.

2 semaphore pending.

Handler took semaphore.

1 semaphore pending.

Handler took semaphore.

0 semaphore pending.

Tick.

0 semaphore pending.

ISR gave semaphore.

1 semaphore pending.

 なお本来であれば、カウンティングセマフォに入っているセマフォの数のカウントはOS自体の機能として備わっているのが望ましいと考えられます。ただFreeRTOS自体には、カウンティングセマフォ用のセマフォのカウント用関数は用意されていません。またキューのカウント用関数であるuxQueueMessagesWaiting関数を使ってみたところ(freertos_interrupt_counting_semaphore_tim4_get_num_by_func)、実際のセマフォの数とはずれが出ました。今後の改善に期待したいところです。


Previous: 5.1.4. バイナリセマフォを取る

Up: 5. 割込み処理

Next: 6. クリティカルセクション


このページはITと知的財産の法律情報「法務ネット」の管理人が制作・運営しています。