2017-10-20 22 views
0

私はARM組み込みデバイスでRTOSディストリビューションを使用しています。 現在、私は何を私が気づいたことは、いつどこで、私は(1-2ms信号は完全に間違っていることができます(別のスレッド/タスク)は、この関数を呼び出すに基づいていることである。このRTOSのvTaskDelayとのピンのトグル

GPIO_Write(PIN_1, LOW); 
vTaskDelay(msec_to_ticks(1)); 

GPIO_Write(PIN_1, HIGH); 
vTaskDelay(msec_to_ticks(1)); 
GPIO_Write(PIN_1, LOW); 
vTaskDelay(msec_to_ticks(3)); 

GPIO_Write(PIN_1, HIGH); 
if (option1){ 
    vTaskDelay(msec_to_ticks(3)); 
    GPIO_Write(PIN_1, LOW); 
    vTaskDelay(msec_to_ticks(1)); 
} else { 
    vTaskDelay(msec_to_ticks(1)); 
    GPIO_Write(PIN_1, LOW); 
    vTaskDelay(msec_to_ticks(3)); 
} 
GPIO_Write(PIN_1, HIGH); 
if (option2){ 
    vTaskDelay(msec_to_ticks(3)); 
    GPIO_Write(PIN_1, LOW); 
    vTaskDelay(msec_to_ticks(1)); 
} else { 
    vTaskDelay(msec_to_ticks(1)); 
    GPIO_Write(PIN_1, LOW); 
    vTaskDelay(msec_to_ticks(3)); 
} 
GPIO_Write(PIN_1, HIGH); 
vTaskDelay(msec_to_ticks(3)); 
GPIO_Write(PIN_1, LOW); 

のような信号をトグルする必要性によオフ)。

taskENTER_CRITICAL()とtaskEXIT_CRITICALを使用すると、やや正確な信号を確認できますか?

私が持っているアイデアは、優先度の高い割り込みがどこかでコードを遅らせることがあるということです(タスクに最大優先度を設定していますが)。 もう1つはタイミングが正しいことですが、GPIO_Writeはすぐには発生しません。

コードが中断されないようにするにはどうすればいいですか?

よろしく、

答えて

0

はここで考えるべきいくつかのことです。

1)vTaskDelay()で使用されるタイマーの期間は何ですか?遅延期間内のエラーの量は、1ダイクまでです。たとえば、次のティックが起きる直前にディレイを開始すると、遅延は1ティックまで短くなりすぎる可能性があります。

ティック時間が1ミリ秒の場合、タイマーの解像度が比較的低いため、遅延が1ミリ秒まで、または100%短すぎることがあるため、正確に1ミリ秒の遅延を測定することはできません。うまくいけば、ティックピリオドは0.01ミリ秒以下です。これは1ミリ秒以下で1ミリ秒を測定できるからです。 vTaskDelay()は、定期的なタスクの頻度を制御するための良い方法ないである理由

2)FreeRTOS documentationは説明しています。

vTaskDelay()タスクがvTaskDelay()が呼び出された時刻に 相対のブロックを解除したい時刻を指定します。たとえば、ブロックタイマー100ティックを指定する は、vTaskDelay()が呼び出された後に、タスクがブロック番号 を100ブロック解除する原因になります。したがって、 vTaskDelay()が呼び出される頻度に影響し、したがって、コードを介して取られた経路として 周期タスクの頻度を制御する良い方法を提供します。したがって、他の タスクおよび割り込みアクティビティは、次のタスク が実行されます。固定周波数実行を容易にするように設計された別のAPI関数 については、vTaskDelayUntil()を参照してください。 によってこれを実行し、 呼び出しタスクがブロックを解除する絶対時間(相対時間ではなく)を指定します。

3)の周り​​とtaskEXIT_CRITICALを使用して私には悪いアイデアだと思いvTaskDelay()に呼び出します。 vTaskDelay()を呼び出す理由は、このタスクが遅れている間に他のタスクを実行する機会を与えることです。だから、​​で割り込みを無効にすることは非生産的なようです。遅延中に他のタスクを実行したくない場合は、vTaskDelay()ではなく、非ブロック遅延関数を呼び出します。その後、ノンブロッキング機能のタイミングがまだ割り込みの影響を受けている場合は、それをクリティカルセクションに入れることを検討できます。これは最初の前に、単一の目盛り遅延を挿入することによって解決することができる

Tick: |   |   |   | 
     ________  __________ 
Signal:  |____|   |__________________ 
      <---------> 
     First transition 
    may occur anywhere here. 

+0

最初のトランジションだけがティック境界と非同期になります。他のトランジションはすべて直ちに遅延の後に続くためです。つまり、遅れが1ティックの遅延(優先度の高いタスクや割り込みの許可)に続く場合は、1ティックの遅延を正確に生成できます。 – Clifford

0

一つの問題は、最初のピンのセットがRTOSクロックに非同期に発生するので、クロック周期のどこにでも発生する可能性があることです遷移。

Tick: |   |   |   | 
     __   __________ 
Signal: |__________|   |__________________ 
Delay(1)-^   
     Transition occurs on the tick boundary 

優先度の高いタスクや割り込みはトランジションや原因のジッタを遅らせる可能性がありますが、スケジューラまたは無効に割り込みをロックした場合、それらのタスクは実行されません、そして、あなたのアプリケーションは、これらのタスクが割り当てられているされていることを取ることができるかどうか不適切な優先順位。同様に、ジッタが重要な場合は、再度、優先度の高いタスク、または逆に不適切な挙動とスケジューリング可能性の高いタスクが優先度の高いタスクに割り当てられます。

タスクの優先度はスケジューリング可能性と期限についての「重要度」ではありません。指針として、ハードリアルタイムデッドラインを持ち、短い決定論的期間に実行されるタスクは、高い優先度を持つべきである。この場合、タスクはほとんどの時間を遅延させるため、GPIOスイッチのクロックサイクルは非常に少なくなります。したがって、このタスクにはおそらく高い優先度を割り当てることができます。

決定的に動作しないタスクは、時間が重要なタスクに影響を与えないように優先順位を低くする必要があります。このフラグメントが他の多分非決定論的なものを実行するタスクの一部である場合、タスク分割は再考する必要があります。タスク分割は必ずしも「ジョブ」に関するものではなく、スケジューリング可能性に関するものであり、直感的に単一の機能または動作を複数のタスクに分割する必要があります。例えば、この信号は、優先度の低いタスクで直接実行されるのではなく、優先度の低いタスクによってトリガされるイベントを待つ高優先度のタスクによって生成される場合があります。