お腹.ヘッタ。

関数型とかセキュリティとか勉強したい。進捗つらぽよ

Arduinoでのスレッドのお話。(pt.h)

こんにちわ。備忘録も兼ねてArudinoのスレッドのお話です。

別々のスピードでステッピングモーターの動作をやらせたいってことがあって、それ故Arudino上でスレッドを立ててみました。

github.com


以上今回のやっつけソースです。

そもそもArudinoにはスレッドの機構は存在はしないのですが、組み込み機器の考えの中にはRTOS(リアルタイムオペレーションシステム)を使うスレッドの組み込み機器とRTOSを使わない(ポーリング型(いわゆるイベント駆動型)プログラミング)の組み込み機器があります。その後者を簡単にするために"protothreads"というライブラリがあります。
protothreads
要参照。

要は今回のはprotothreadsをarudino向けにラップしたやつの紹介ということになります。



さてここからがこのエントリの本題で備忘録です(遠い目)

pt.hのinclude

Arduino Playground - TutorialList
から
build hardware and write code for it: protothread, a powerfull library
へ行って
Google Code Archive - Long-term storage for Google Code Project Hosting.
pt.hをダウンロードしてください。

その際includeすると

#include <lc-addrlabels.h>
#include <lc-switch.h>
#include <lc.h>
#include <pt-sem.h>
#include <pt.h>

ってでてくるので
削って

#include <pt.h>

に変えてコードを書く。やるだけ。




さてこいつの困ったのは意外に日本語情報あまり多くないんですね。。。
そしてぶっちゃけ二番煎じなんでオレオレメモ書きリファレンスも残しておきたいと思います。

(オレオレ)リファレンス

struct pt {
  lc_t lc;
};

構造体型pt。それだけ

PT_INIT(pt);
/*実態は
#define PT_INIT(pt)   LC_INIT((pt)->lc)
ってなっておりlc.hでincludeされている"LC_INIT(lc)"でその使用するスコープ変数の状態を初期化している
*/

Protothread を初期化する。

 PT_THREAD(name_args);
/*実態は
#define PT_THREAD(name_args) char name_args

名前を引数として呼ぶって感じですね。
*/

protothread (ちなみにCで記述されてる)の宣言部分らしい。

PT_BEGIN(pt)
/*実体は
#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
"LC_RESUME(lc)"はlc.hで記述されてて意味どおりスレッドの再開をするってこと。つまるところスレッドの開始ということになる。
*/

protothread の開始の宣言。

PT_END(pt)
/*実体は
#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
                   PT_INIT(pt); return PT_ENDED; }
"LC_END(lc);"はlc.hで記述されててそのスコープでの使用の終了をマークしてる関数。
*/

Protothread の終了を宣言。

PT_END(pt)
/*実体は
#define PT_WAIT_UNTIL(pt, condition)	        
  do {						
    LC_SET((pt)->lc);				
    if(!(condition)) {				
      return PT_WAITING;			
    }						
  } while(0)
" LC_SET(lc);"はlc.hで記述されててそのスコープでの使用を設定する関数。正確に言うとその状態に保存をかける関数。
*/

protothread の宣言したスコープのスレッドで止まる。つまり機能的にはwait関数。

PT_EXIT(pt)
/*実体は
#define PT_EXIT(pt)				
  do {						
    PT_INIT(pt);				
    return PT_EXITED;			
  } while(0)
*/

protothread の宣言したスコープを終了させる。

PT_SCHEDULE(f)
/*実体は
#define PT_SCHEDULE(f) ((f) < PT_EXITED)
*/

protothreadをスケジュールをするために使うぽい。具体的にはprotothread が終了した場合0を返す。

PT_YIELD(pt)	
/*実体は
#define PT_YIELD(pt)				
  do {						
    PT_YIELD_FLAG = 0;				
    LC_SET((pt)->lc);				
    if(PT_YIELD_FLAG == 0) {			
      return PT_YIELDED;			
    }						
  } while(0)
*/

このprotothread(スレッド)が終わるまで待つ。
片方でデータ通信しててそのデータをもう一つのスレッドで仕事したい時に使うとでも言えばイメージがつく。

PT_YIELD_UNTIL(pt, cond)
/*実体は
#define PT_YIELD_UNTIL(pt, cond)		
  do {						
    PT_YIELD_FLAG = 0;				
    LC_SET((pt)->lc);				
    if((PT_YIELD_FLAG == 0) || !(cond)) {	
      return PT_YIELDED;			
    }						
  } while(0)
*/

このprotothread(スレッド)の指定した条件が true に評価されるまで待つ。

以上おまけでした。間違えがあったら教えてくれると助かります。