1. ホーム
  2. c

[解決済み] vTaskDelayと_delay_msの動作の違いは何ですか?

2022-02-15 04:06:07

質問

1. はじめに

FreeRTOSのタスクにおける以下の機能の動作の違いについて、情報や詳しい説明が見つからないようです。

  • vTaskDelay
  • 遅延時間_ms

2. コード

以下のようなコードがあったとします。

IdleHook + タスク作成

Long value = 0;

void vApplicationIdleHook( void ) {
    while(1)
    {
        // empty
    }
}

int main(void)
{
     xTaskCreate(TaskIncrement, (const portCHAR *)"up" , 256, NULL, 2, NULL );
     xTaskCreate(TaskDecrement, (const portCHAR *)"down" , 256, NULL, 1, NULL );

     vTaskStartScheduler();
}

vTaskDelayを使用したタスク

static void TaskDecrement(void *param)
{
    while(1)
    {
        for(unsigned long i=0; i < 123; i++) {
            //semaphore take
            value--;
            //semaphore give
        }
        vTaskDelay(100);
    }
}

static void TaskIncrement(void *param)
{
    while(1)
    {
        for(unsigned long i=0; i < 123; i++) {
            //semaphore take
            value++;
            //semaphore give
        }
        vTaskDelay(100);
    }
}

delay_msを使用するタスク

static void TaskDecrement(void *param)
{
    while(1)
    {
        for(unsigned long i=0; i < 123; i++) {
            //semaphore take
            value--;
            //semaphore give
        }
        _delay_ms(100);
    }
}

static void TaskIncrement(void *param)
{
    while(1)
    {
        for(unsigned long i=0; i < 123; i++) {
            //semaphore take
            value++;
            //semaphore give
        }
        _delay_ms(100);
    }
}

3. 質問事項

タスクにvTaskDelayと_delay_msを指定した場合、プログラムの流れはどうなるのでしょうか?

注:与えられた2つのタスクの例では、優先順位が異なっています。

解決方法は?

から https://www.freertos.org/Documentation/FreeRTOS_Reference_Manual_V10.0.0.pdf :

vTaskDelay()を呼び出したタスクは、一定のtick数の割り込みの間、Blocked 状態になります。遅延時間を0tickで指定すると、呼び出し元のタスクはBlocked状態になりませんが、呼び出し元のタスクは、優先度を共有するReady状態のタスクに降参することになります。vTaskDelay(0)を呼び出すことは、taskYIELD()を呼び出すことと同じです。

もうお分かりだと思いますが、複数のタスクが作成されている場合は vTaskDelay() は、実行中のタスクを指定された tick 割り込み数 (ミリ秒ではありません!) の間 "Blocked" 状態にし、次に高い優先度を持つタスクが制御を放棄する (FreeRTOS の設定によってはプリエンプトされる) まで実行できるようにします。

私は _delay_ms() はFreeRTOSのライブラリに含まれています。 本当にプラットフォーム固有の関数ではないのでしょうか? 私の推測では、最も優先度の高いタスクが _delay_ms() であれば、ビジー状態の待ち時間が発生します。 そうでなければ、より高い優先順位を持つタスクが、そのタスクが呼び出した _delay_ms() を遅延させているため(つまり。 _delay_ms() は、すぐに制御ができるわけではありません)。

おそらく、上記をよりよく要約すると、マルチタスクのアプリケーションでは、次のようになります。 _delay_ms() は決定論的ではありません。