クリティカルセクションに関してラッピングをした。
これは以下ページの内容のもの。
Spinlock
spinlock_tを使うものだったため、上のようなクラス名にして見た。
形式としてstd::mutexと同じような構成にしてある。
そのためstd:: lock_guardを使ったScoped Locking手法が利用できる。
サンプルはこちら。
Test1とTest2というクラスがあり、Test2でtask全体(ブロック)にロックをかけている。
これを動かすと、Test2のtaskだけしか動かなくなるといったもの。
これはTest1とTest2を同一のコア、同一の優先順位で動かしているのだが、Test2側のタスク全体をロックしてほかのタスクに時分割で遷移できないようにしているため。
Test1とTest2が別のコアで動作していれば、両方とも動作するようになる。
タスクスイッチ関連の覚書
ESP32-freeRTOSのtask関連ラッピングクラスと今回のを合わせてちょっといろいろ調べてみたところ、以下の様な感じのことが分かったのでとりあえず書いておく。
クリティカルセクション内でのブロック動作
上のSpinlockでサンプルを作成していた際に気が付いた点なのだが、タスクをRunning状態にするためと時間を計測したいがためets_delay_usを使っていた。
試しに、これをvTaskDelayに変更して試してみたところ、時間調整を全くしてくれなくなった。
2msのdelayをしたかったのだがvTaskDelayを使用した場合の時間はほぼ0となった。
クリティカルセクションを外すときちんとほぼ指定した時間の調整がされてはいた。
クリティカルセクションはプリエンプティブコンテキストスイッチとISRのサービスが防止されとなっているが、タスクのブロック遷移(vTaskDelayの呼び出し)はコンテキストスイッチの防止に含まれるのだろう。
多分レアケースなのだとは思うが注意したい内容だと思う。
ets_delay_usの利用
複数のタスクをets_delay_usで時間調整をする場合、どんな感じに時間調整がされるのかちょっと調べてみた。
まずは同一コアに対して2msごとにピンをH/Lさせるプログラムをコンテキストスイッチ間隔を10msにした場合。
短い部分のH/Lの変化は2msに納まっているがタスクがスイッチした瞬間伸びる。
その間タスクが止まるので当然なのだが。
次はスイッチ間隔を1msにした場合。
この場合、H/L間隔は両タスクとも2msにかなり近い値で動いていた。
ちょっとこれにはびっくりした。
想定では4ms間隔かもうちょっと間隔がバラバラになるのかなと思っていたのだが。
次にスイッチ間隔を2msにした場合。ets_delay_usで指定した時間とほぼ同じ時間にした場合。
この場合は、H/L間隔が4msに近い値となっていた。
時間調整ではets_delay_usが一番精度が高いが、上の1msの場合のは例外でets_delay_usを使う場合はクリティカルセクションで囲むか、vTaskDelay系を使うのが良いのだろう。
コメント