ESP32-タイマーGeneral Purpose Timerのラッパークラス

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/timer.html#

これのラッパークラスを作成。

librarieseesp32/lib/freertos_utility/src/Timer.h at master · take4blue/librarieseesp32
Contribute to take4blue/librarieseesp32 development by creating an account on GitHub.

初めに作成したのはテンプレート形式のクラス(https://github.com/take4blue/librarieseesp32/blob/master/lib/freertos_utility/src/TimerT.hpp)なのだが、IRAM配置の問題でちょっと使いづらくなったので、単純なクラスにしたものに作り直した。ここらあたりの問題点は後で。

Timerクラス

基本的にtimer_~関連の関数をクラス内に押し込め、Timer groupとTimer indexを意識しなくても使えるようにしたもの。

初期化のためのbeginは2種類用意し、関数指定がないものは単純なタイマーとして使い関数指定があるものは割り込み可能なタイマーとして利用できるようにしている。

割り込みについて

割り込みの関数は、使用するクラス側にクラスメソッドのCallbackFunctionの型で用意しておく必要がある。

この割り込み関数については、以下の様な実装上の注意点がある。

  1. 割り込み関数自体をIRAM配置してある前提として内部の処理を行っている。
  2. 割り込み関数内でvoid*を時オブジェクトに型変換し利用する必要がある。
  3. beginで渡すvoid*にthisを指定し、割り込み関数内で渡ってきたvoid*を自分のクラスに型変換して使う必要がある。

オブジェクトサイズ

割り込み用のメンバー変数(割り込み関数とvoid*用)を保持したため、若干大きくなってしまった。

TimerTクラスとその実装時の問題点

こちらはテンプレートクラスで対応したもの。

内部で型変換を行うことで実装クラス側の特定メソッドを呼び出す形にしていたため、オブジェクトのサイズも肥大化せず、使う側での割り込みメソッドの定義などがしやすいというメリットがあった。

ただ、実装して使ってみたところ特にIRAM配置に関する問題が浮上したため別途単純なクラスを作成しなおすことになった。

テンプレートメソッドで定義したIRAM属性が無視される

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70435

この問題によりテンプレートクラス内のstaticメソッドにIRAM_ATTRを付けたのだがそれがないことになってしまっていた。

このため、begin()内でtimer_isr_callback_addをESP_INTR_FLAG_IRAM付きで呼び出すとtimer_isr_callback_addでエラーになるといった現象が発生した。

当初この理由が分からず、原因が判明するまで結構時間がかかってしまった。

この対応をするには、IRAM属性無しで実装を行うか、呼び出し側に実装した割り込み関数を指定させるかどちらかしかなった。

そこで、外部割込み関数を用意できるような仕組みにしたのだが、割り込み時に必要な処理をセットで持たせたかったので、それをちょっとだけ隠蔽できるようにマクロを用意するといったなんともやるせない実装になってしまった。

結局ここまでやるのであれば、テンプレート化までは必要ないと判断した。

補足

ちなみにラッパークラスを作成しているのは、不必要なものを隠蔽して実装しやすくするというのと、サンプル的なものを作成して実装時に再利用したかったから。

これをライブラリ化しておけば再利用も参照もしやすくなるので。

コメント

タイトルとURLをコピーしました