Micro Core Library for AVR (Arduino)

今までに作ったライブラリの中でも個人的に便利で気に入ってるものを集めてAVR(Arduino)用に再構成してみた。

【概要】

・MCore (ボード依存機能, digispark/leonardo/unoのLED設定など)

各ライブラリの初期化とボードのビルトインLEDのセットアップ、バックグランド処理やタスクスイッチング等を行う。

・Led (LED管理)

今までLED制御(Lチカ)をライブラリ化する発想など全くなかったが時間指定でLEDを制御できるのは意外に便利だ。LEDってどのピンに接続されていて光らせるためにはどうればいいんだったっけ?などと毎回回路図を探しまくってしまうLEDの管理ができるだけでも有り難い。

・Alarm (タイマー割り込み/ポーリング)

一個のハードウェア・タイマーのみでマイクロ秒精度のタイマー割込を制限なく提供する。それなりのオーバーヘッドはあるもののメリットがデメリットを上回ると言える便利さがある。また、割込を使わないポーリング機能はシンプルにコーディングできてクセになりそうだ。

※アラーム機能はTIMER0を利用している。TIMER0のPWM機能を使うと誤動作することに注意。

・Task (タスク管理)

ATtiny85でも動作するシンプルで省メモリな協調型マルチタスク機能は学習用にもいいかもしれない。但し、ATtiny85ではメモリの余裕がないので規定のスタックサイズでは1タスクのみしか動作しない。2タスク動作させるにはスタックサイズの調整が必要である。必要なスタックサイズは単純なプログラムで確認したところ64バイト未満だったので余裕をみてその2倍の128バイトをスタックサイズの規定値としているが単純なプログラムであれば80~90バイト程度あれば問題はないと思う。より大きいスタックサイズを必要とするプログラムでは適切な調整が必要となる。

・Fifo (バッファ管理)

世の中のRTOSでは標準機能となっているメールボックスやメッセージバッファを実装したライブラリ。テンプレートクラスにより様々なデータ型が扱えるようになっている。データ取得できるまでタスクはスリープして待つので効率の良いシステムの構築には必須かも。使い方次第でメールボックス或いはメッセージバッファのどちらとしても利用できるはずだ。

・Hardware (ハードウェア依存処理)

ハードウェア依存のコードを集めてあるのでクラス実装を追加するだけで他のCPUやOSにも対応可能だ。

【basic.ino】

【blink.ino: auto blink】

【alarm1.ino: alarm interrupt】

【alarm2.ino: alarm polling】

【task.ino: multi task】

【fifo.ino】

【download】

mcore-avr.zip (Arduino Library)

【update】
2022-06-29
昨日のSemクラスの修正の修正。

2022-06-28
Semクラスのタイミングバグ修正とTask::start()に負数のスタックサイズ指定をしたとき登録タスクではなく直前の登録タスクのスタックサイズ指定になっていて混乱しやすいので修正。

2022-06-24
Fifoクラスにオーバーライト機能を追加。

2022-06-23
Semクラスのバグ修正とTaskクラスのチューニング。それと2レベルではあるがタスク優先度を追加し起床タスクの優先度を一時的にあげる仕組みを追加してみた。リアルタイムにはスイッチングしないが休止状態から起床されたタスクが最優先で実行されるようになる。可能ならリアルタイム性を追加したいところではあるがリアルタイムやタイムスライスに対応すると標準ライブラリを含む全てのライブラリもマルチスレッド対応にする必要があったりしてとても大変なことになるで対応はしない。

2022-06-21
Task::start()の最適化を行った。

2022-06-20
Taskクラスの微妙な感じがしていたタスク切り替え処理を改良してみた。今のところ対応は考えてないけどタイムスライスも行けそうな感じになってきた気がする。

2022-06-18
Fifoクラスのバグ修正。

2022-06-17
Fifoクラスの仕様変更を行った。

2022-06-16
Fifoクラスを追加。

2022-06-15
Sync/Mutex/Sem/Eventクラスのコード最適化の続きを行った。

2022-06-14
Sync/Mutex/Sem/Eventクラスのコード最適化を行った。

2022-06-13
Eventクラスがバグッてたので修正。

2022-06-12
Task::start()で指定するタスクのスタックサイズが割り当てモード毎に違っていて混乱するのでスタックサイズにはTask::TCB_SIZEを加算したサイズが指定されているものと仮定した仕様変更を行った。

例えば、スタックサイズとして128バイトを指定する場合は
128 + Task::TCB_SIZE
を指定しなければならない。(AVRのTask::TCB_SIZEは31バイト)

2022-06-11
いつの間にかタスクが動作しなくなっていたのとSem/Mutex/Eventのウェイト処理のタイミングバグを修正。あとメッセージバッファのような機能を作りやすくするためSemクラスのwait()/post()にカウント値引数を追加。

2022-06-10
Semクラスコンストラクターにカウンター初期値を設定するための引数を追加

2022-06-09
タスク終了時のタイミングバグを修正。

2022-06-08
Sync::sleep()のバグ修正と割り込み禁止期間のチューニングを行った。

【MCore】

ライブラリの初期化とボードのビルトインLEDのセットアップを行う。

バックグラウンド処理とタスクスイッチングを行う。

【Led】

登録番号、LED出力ピン、LEDオフ出力値を指定してLED登録する。

指定時間後にLEDを消灯する。

指定時間後にLEDを点灯する。

指定時間後にLEDの点灯状態を反転する。

LEDの点灯状態を返す。

LEDタイマー指定後に指定時間が経過したかどうかを返す。

【Alarm】

アラーム割り込みハンドラー型の定義。

アラーム・インターバル(マイクロ秒)を設定する。アラームタイマー割り込み処理でインターバルを変更するときはfromnowをfalse指定すること。

アラーム・インターバル(マイクロ秒)を取得する。

アラーム割り込みハンドラーを設定する。

アラーム割り込みハンドラーを取得する。

アラーム引数を設定する。

アラーム引数を取得する。

アラーム時刻が過ぎたかどうかを返す。ポーリング専用。

【AlarmClass】

アラーム・タイマーを開始する。

アラーム・タイマーを取消する。

アラーム・タイマーを取消する。

【Task】

タスク関数型。

タスクを登録する。sizeに負数指定時は現在のスタックを分割使用し正数指定時はスタック領域のサイズと見なす。stackに静的配列変数アドレスを指定時はその変数領域をスタック領域とし、stackにゼロ指定時はmalloc()により動的にスタック領域を割り当てる。malloc割り当て時はタスク終了時にfree()されるため動的なタスク生成/終了が可能。

タスクを終了する。メイン・タスクは終了できない。

ラウンドロビン・アルゴリズムにより次の実行待ちタスクへ切替える。MCore::handle()からも呼び出されるが協調型マルチタスクはこの関数の実行でのみタスク切替が起こるためタスク処理内では積極的にこの関数を呼び出す必要がある。逆に言えばこの関数を呼び出さない限りCPUを占有することができるということになりそれがメリットにもなりえたりする。

カレントタスクの識別子を返す。

指定時間(ms)休止する。タスクはアラームタイマー割り込みにより起床される。正確な時間を要求するためにbusyLoopを指定した場合は指定時間のbusyLoop前に起床した後ビジーループにより正確な時間判定を行う。最大約35分まで指定可能。

指定時間(us)休止する。タスクはアラームタイマー割り込みにより起床される。正確な時間を要求するためにbusyLoopを指定した場合は指定時間のbusyLoop前に起床した後ビジーループにより正確な時間判定を行う。最大約35分まで指定可能。

指定時間(ms)待つ。指定時間経過するまでタスクはyield()を繰り返す。正確な時間を要求するためにbusyLoopを指定した場合は指定時間のbusyLoop前からビジーループにより正確な時間判定を行う。最大約71分まで指定可能。

指定時間(us)待つ。指定時間経過するまでタスクはyield()を繰り返す。正確な時間を要求するためにbusyLoopを指定した場合は指定時間のbusyLoop前からビジーループにより正確な時間判定を行う。最大約71分まで指定可能。

【Sync】

コンストラクター。

指定時間経過するまで休止する。timeoutに負数指定時はwakeupされるまで待ち続け、正数指定時はwakeupにより起床された場合はtrue、タイムアウト時はfalseを返す。最大約35分まで指定可能。

休止タスクを起床する。taskにゼロ指定すると休止タスク順に起床されゼロ以外を指定するとそのタスク識別子をもつ休止タスクを検索して見つかれば起床する。起床したタスク識別子を返しタスクが起床できなければゼロを返す。割り込み処理からも呼び出すことが可能。

【Mutex】

コンストラクター。

ロックする。多重ロックが可能。timeoutに負数指定時はロックを獲得するまで待ち続け、正数指定時はロックを獲得できた場合はtrue、タイムアウト時はfalseを返す。最大約35分まで指定可能。

アンロックする。多重ロックが全て解除されたときにアンロックされる。割り込みは不特定のタスク実行中に割り込んでくるため割り込み処理から呼び出してはいけない。

【Sem】

コンストラクター。limitにはカウント最大値を、countにはカウント初期値を指定する。

カウントを取得する。timeoutに負数指定時は取得できるまで待ち続け、 正数指定時は取得できた場合はtrue、取得できなかった場合はfalseを返す。最大約35分まで指定可能。

カウントを返却する。割り込み処理からも呼び出すことが可能。

【Event】

コンストラクター。 実装はバイナリセマフォであり単一イベントにのみ対応している。

イベントを取得する。timeoutに負数指定時はイベント取得できるまで待ち続け、 正数指定時はイベント取得できた場合はtrue、イベント取得できなかった場合はfalseを返す。

イベントを通知する。割り込み処理から呼び出すことが可能。

【Fifo】

テンプレート引数。

コンストラクター。

データを取得する。timeoutに負数指定時は取得できるまで待ち続け、 正数指定時は取得できたカウントを返す。

データを追加する。timeoutに負数指定時は追加できるまで待ち続け、 正数指定時は追加できたカウントを返す。割り込み処理から呼び出すことも可能であるがtimeout引数にゼロ指定する必要がある。割り込み処理からtimeout引数にゼロ以外を指定し呼び出した場合はバッファフル時にタスクスイッチ(yield)してしまい誤動作することに注意。

【library】