2012年09月26日

Propeller gccでpthreadライブラリを使ってマルチタスクしてみる

以前プロペラのgccがあるよ、という話を伺った時、propellerスレッドライブラリあったら面白いねーとか話していたのですが、Pellerduinoのコア(PellerduinoCore)をいじってて、普通にpthreadライブラリあるじゃないかと気づきました。

プロペラのpthread実装がどのようなコードになっているのか、非常に気になるところです。
その前にひとまず、pthreadライブラリを使ってマルチタスクがお手軽に出来るのか?を実験をしてみることにしました。

Propeller_QS.jpg
以下がテスト用に作成したコード。
/*
  LED Blink test for QuickStart board

  Coded by Yasuhiro ISHII
*/

#include 

extern "C" {
#include 
}

#include 

const int pinTable[8] = {
    PIN_LED0,
    PIN_LED1,
    PIN_LED2,
    PIN_LED3,
    PIN_LED4,
    PIN_LED5,
    PIN_LED6,
    PIN_LED7
};

pthread_t th[8];
pthread_mutex_t gpio_mutex;
void synchronized_digitalWrite(int port,int level);

void busywait(unsigned int usecs);

void* thread(void* arg)
{
    int i;

    i = (int)arg;
    pinMode(pinTable[i],OUTPUT);

    while(1){
	printf("thread [%d]\n",i);
	synchronized_digitalWrite(pinTable[i],HIGH);
	delay((i+1)*100);
	synchronized_digitalWrite(pinTable[i],LOW);
	delay((i+1)*100);
    }
}

void synchronized_digitalWrite(int port,int level)
{
    pthread_mutex_lock(&gpio_mutex);

    digitalWrite(port,level);

    pthread_mutex_unlock(&gpio_mutex);
}

void busywait(unsigned int usecs)
{
  volatile unsigned long cycles = usecs * (_clkfreq/1000000);
  volatile unsigned long then = _CNT + cycles;
  while((long)(then - _CNT) > 0){
//      pthread_yield(); 
  }
}

void setup()
{
    int i;

    pthread_mutex_init(&gpio_mutex,NULL);

    for(i=0;i<8;i++){
      pinMode(pinTable[i],OUTPUT);
    }

    for(i=0;i<8;i++){
	pthread_create(&th[i],NULL,thread,(void*)i);
    }
}

void loop()
{

}
Pellerduinoはpthread.aをリンクしてないので、ひとまず以下のMakefileにてビルド。
# Propeller build Makefile
#
# Yasuhiro ISHII 2012
# ishii.yasuhiro@gmail.com

CROSS_ENV	=  propeller-elf-
CC		=  $(CROSS_ENV)gcc
CPP		=  $(CROSS_ENV)g++
CFLAGS		=  -Os -I. -fno-exceptions -mlmm -lpthread -pthread
CPPFLAGS	=  -Os -I. -fno-exceptions -mlmm -lpthread -pthread
LCFLAGS		=  -pthread -lpthread
TARGET		=  target.elf
OBJS		=  main.o
DOWNLOADER	=  propeller-load
DLOPT		=  -r


COMMONOBJS	=  PellerduinoCore.o

OBJS		+= $(COMMONOBJS)
#CFLAGS		+= -Wall -mcog

.c.o:
	$(CC) $(CFLAGS) -c $<
.cpp.o:
	$(CPP) $(CPPFLAGS) -c $<

$(TARGET) : $(OBJS)
	$(CC) -o $@ $(OBJS) $(LCFLAGS)


.PHONY: clean
clean:
	-rm $(OBJS) $(TARGET) $(COMMONOBJS)

.PHONY: purge
purge:
	-rm *~

.PHONY: download
download:
	$(DOWNLOADER) $(DLOPT) $(TARGET)
コードはPellerduinoCoreからの呼び出しになっているので、Arduino同様、setup()→loop()で実行されます。
setup関数内で、I/O操作用のmutexをpthread_mutex_init関数で行った後、pthread_create関数で8スレッド起動しています。digitalWriteは同一ポート資源のコントロールをするので、スレッドからは、mutexで排他性を確保したsynchronized_digitalWriteを呼ぶようにしています。
それぞれのスレッドにそれぞれ1つのLEDを点滅させるのですが、スレッドに渡す引数の値で点滅周期が変化するようにしているので、バラバラの点滅パターンになっているように見えるはずです。
loop関数は空関数で何もしません。

動画はこちら。

なんとなく、Arduinoっぽいコードの枠組み内にpthreadを使用したマルチタスクの処理とか非常に不思議な感じのコードになってますが、以下の動画のように、なんとなくうまく動いてるようです。
複数のcogが使われているのか否かなどは、調べていきたいと思います。
もしかすると、複数cogで実行している場合、gpioのmutexは不要かもしれません。(I/Oの資源も個々に独立しているのなら)

コードは以下のPellerduinoCoreにも入っています。
https://github.com/yishii/PellerduinoCore
Netduino(Arduinoピンコンパチ.NETマイコンボード)
Secret Labs LLC
売り上げランキング: 59733
Pthreadsプログラミング
Pthreadsプログラミング
posted with amazlet at 12.09.26
Bradford Nichols Dick Buttlar Jacqueline Proulx Farrel
オライリー・ジャパン
売り上げランキング: 238987
posted by いしいっち at 22:08| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2012年09月20日

Propeller用ArduinoベースIDE PellerduinoをLinuxで動作させる

先日以下のgithubリポジトリで開発を開始しましたArduino IDEベースのPropeller用IDE Pellerduinoですが、あんまりそれから進んでません^^;
https://github.com/yishii/Pellerduino

Arduino IDEはMacOSX、Windows、Linuxに対応していますが、先日私がPellerduinoとして手当てしたのはMacOSXの範囲まででした。
その後、@ksksue氏がこのPellerduinoを使用してUbuntuで動かすレポートを記載されました。ありがとうございます〜。

ksksue.com UbuntuへのPellerduinoインストール手順
http://www.ksksue.com/wiki/doku.php?id=wiki:propeller:pellerduino:install

というわけで、さっそくPellerduinoにLinux用Propeller gccを組み込み、antから展開されるようにしてみました。今回は、Linuxの64ビット環境のみの対応です。

git clone https://github.com/yishii/Pellerduino.git

本例(Ubuntu 10.04LTS 64bit)でビルドする場合、antを入れておきます。その他のディストリビューションではなければ入れておいて下さい。
sudo apt-get install ant

それから、buildディレクトリに入って、antでビルド・実行します。

# ant run

リリースパッケージの生成方法
ant runした時のパッケージにはバージョン番号などが入っていません。そういったものも含めてリリースパッケージを生成するには、ant distを使用します。

ant dist

すると、以下のような問い合わせが表示されます。

dist:
[input] Enter version number: [0101]

適当に0200とでも入れます。
ビルド・リリースパッケージ生成が終わると以下のように表示されると思います。



linux-dist:
[echo]
[echo] =======================================================
[echo] Arduino for Linux was built. Grab the archive from
[echo]
[echo] build/linux/arduino-0200-linux.tgz
[echo] =======================================================
[echo]

linux64-dist:

そうすれば、上記のログに吐かれているパスに開発環境のアーカイブが出来ます。ファイル名、pellerduino-${version}-ターゲット.tgzにしとこう・・・。取り出して展開するとリリースされているArduinoと同様の構成のパッケージになっているはずです。

実行結果。適当に入れたバージョン番号のIDEになりました。
linux_pellerduino_ss.jpg



PICで楽しむAndroidアクセサリの自作
後閑 哲也
技術評論社
売り上げランキング: 42008

posted by いしいっち at 07:10| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2012年09月16日

PIC24FJ64GB002でADK(microchip_solutions_v2012-08-22を使う)

マイクロチップ社のMicrochip Application LibraryはPICの各種マイコンにいろいろな機能を提供してくれるライブラリとサンプルコードの集合体で無料でダウンロードできます。

http://www.microchip.com/mal

最近更新があったようで、2012/8/22版が最新になっています。それまでの版では、Android 4.1でサポートされたAOA2.0の端末と接続した際、PICのADKライブラリがADKバージョンを確認して弾くため、ADKとして認識してくれませんでした。改造すれば認識するようにはなるのですが。

さて、上記の8/22版ではそんな改変せずとも、AOA2.0端末と接続してADKが認識してくれます。
(AOA2.0のHIDや音が通るわけではありません)

というわけで、テスト的にPIC24FJ64GB002に焼きこんでみたら動作しました!
マイクロチップのサンプルコードBasic Communication DemoはPIC24FJ64GB004用があるので、それを一部変更してPIC24FJ64GB002で動作させられるようにしています。

差分パッチファイルを以下にアップします。unified diff形式です。Microchip Application Libraryのスタックは非常に便利で魅力あるものですが、オープンソースで改変を共有するのにルールが難しいようなので、その点使いづらいですね。
PIC24FJ64GB002_ADK_patch_for_microchip_solutions_v2012-08-22.patch.zip


PICで楽しむAndroidアクセサリの自作
後閑 哲也
技術評論社
売り上げランキング: 42008

posted by いしいっち at 10:54| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする