2017-01-14 30 views
1

vTaskDelayUntil()関数で遅延が発生せずすぐに終了する問題があります。ここでは、コードは次のとおりです。FreeRTOS vTaskDelayUntil()がすぐに終了する

TickType_t xLastWakeTime = xTaskGetTickCount(); 
while(1){ 
    if (xSemaphoreTake(xSemaphoreRS485, portMAX_DELAY) == pdTRUE) { 
     printf("S display data %d\n", xTaskGetTickCount()); 
     sendDisplayData(); 
     printf("E display data %d\n", xTaskGetTickCount()); 
     xSemaphoreGive(xSemaphoreRS485); 
     printf("W display data %d\n", xLastWakeTime); 
     vTaskDelayUntil(&xLastWakeTime, 2000); 
    } 
} 

このことから、私は次のような出力が得られます。

S display data 29928 
E display data 30534 
W display data 3919 
S display data 30534 
E display data 31140 
W display data 5919 
S display data 31140 
E display data 31746 
W display data 7919 
S display data 31746 
E display data 32352 
W display data 9919 

sendDisplayDataは()を実行するのに約670ミリ秒かかり、xTaskGetTickCount()関数は、それを確認します。次に、タスクは約1230ミリ秒を待たなければならないので、繰り返し全体が2000ミリ秒かかることがあります。しかし、vTaskDelayUntil()はすぐに終了します。最初の実行は30534で終了し、2番目の実行は30534でも開始されます。 xTaskGetTickCount()によって返された値は、vTaskDelayUntil()によって遅延が導入されなかったことを示します。 sendDisplayData()の出力頻度でも見ることができます。

2番目の面白いことに、xLastWakeTimeは全く異なる値を示し、その値は実際には2000ずつ増えています。xTaskGetTickCount()で返される値と同じ値を保存してはいけませんか?あなたの最初の反復xLastWakeTime

+1

設定ファイルに#define INCLUDE_vTaskDelayUntil 1がありますか?そして、TickType_tを再定義して、符号付き16ビットと言うことはできませんか? TickType_t xLastWakeTime = xTaskGetTickCount();を移動してみてください。セマフォを受け取った後に、適切な値が表示されますか? (これは、最初にvTaskDelayUntilにxLastWakeTime + 2000を既に超過したことが原因であるかどうかをプレーンなチェックのためだけにしたいとは思わないでしょう) – koper89

+0

はい、この定義があり、TickType_tは32ビットタイプです。私の疑問に思っています。もちろん、元のコードは完全ではありませんでした。なぜなら、セマフォを取るには最大10秒かかり、最初のvTaskDelayUntil()はすぐに終了するからです。その変数は5919ではなく、30534に設定されています。 – grzegorz

答えて

5

は値3919を持っており、あなたは2000年の増加、5919までのように遅延を要求していますが、vTaskDelayUntil()

のドキュメントから時間30534.

でそれを求めています

vTaskDelayUntil()は、すでに過去の起床時刻を指定するために使用される場合は、(ブロッキングなしで)すぐに戻ります。

タスクは、初期セマフォで26009ティック(29928 - 3919)をブロックしました。あなたのターゲット2000ダニの増分は、長い過去です。

私はあなたがこれはループ反復は、合計時間は待っていsendDisplayData()プラスを実行するのにかかる時間を含め2000匹のダニを取るようになります

for(;;) 
{ 
    if (xSemaphoreTake(xSemaphoreRS485, portMAX_DELAY) == pdTRUE) // Lock 
    { 
     TickType_t xLastWakeTime = xTaskGetTickCount(); 
     sendDisplayData(); 
     xSemaphoreGive(xSemaphoreRS485); // Unlock 

     vTaskDelayUntil(&xLastWakeTime, 2000); 
} 

を意図したものに近い少なくともある次のことを示唆していますRS485のリソースが利用可能になると思っています。

+0

ここでセマフォは、RS485リンクへのアクセスを同期させるためのミューテックスとして機能し、sendDisplayData()を実行する前にセマフォを取得する必要があります。これは2秒ごとにsendDisplayData()を実行するようにしてください。 それ以降の繰り返しを見てください。どのように5919と7919を30534に関して説明できますか? – grzegorz

+1

@grzegorz:最初の同期後には、セマフォを直前と同じコンテキストで与えているので、何も同期していません。 Jourの「正当化」は、コードがその通りである理由よりも私の答えを理解していないことを示すものです。 semaphoreの待機が必要なのかもしれませんが、同期化を打ち負かす必要があります。これは問題の範囲ではなく、問題の範囲ではありません。この答えはあなたの問題を解決します。 – Clifford

+1

他の反復については - はい、この答えで説明されています。あなたは26000ティック後に始まりますが、それは現在の時刻に追いつく前に2000年までに目標時間を増加させる反復の数を取るでしょう。デバッグ出力から何が起きているのかははっきりしています。 – Clifford

1

上記のとおり、vTaskDelayUntil()は、指定された起床時間がすでに過去になった場合に直ちに戻ります。代わりにvTaskDelay()を使用することを提案してください。

関連する問題