SSブログ

JAVAでbcm2835ライブラリを動かしてみた(その1 失敗) [Raspberry Pi]

(2013.08.27)
Cで書かれたbcm2835ライブラリをJAVAから呼び出す方法を調べ、JNIより手軽に使えるJNA(これ)を見つけました。

早速、サンプル・プログラムをWindowsとRaspberry piで動かしてみました。
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
 
public class Jna_Bcm {
    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary) Native.loadLibrary(Platform.isWindows() ? "msvcrt" : "c", CLibrary.class);
        void printf(String format, Object... args);
    }
 
    public static void main(String[] args) {
        CLibrary.INSTANCE.printf("Hello, World\n");
        for (int i = 0; i < args.length; i++) {
            CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
        }
    }
}

$ java  -jar dist/jna_bcm_1.jar 1 2 3
Hello, World
Argument 0: 1
Argument 1: 2
Argument 2: 3

これにbcm2835ライブラリを追加して、JavaからRaspberry piのGPIOを操作しようという目論みです。(結論として、失敗でした)

先ずC/C++のリモート開発環境を使って、bcm2835ライブラリのシェアド・ライブラリ(libbcmlib.so)を用意しました。そして、サンプル・プログラムにbcm2835ライブラリを呼び出すコードを追加して、ビルド、実行しました。

    public interface BCMLibrary extends Library {
        BCMLibrary INSTANCE = (BCMLibrary) Native.loadLibrary("bcmlib", BCMLibrary.class);
        boolean bcm2835_init();
        void bcm2835_gpio_fsel( final char pin, final char mode);
        void bcm2835_gpio_set(final char pin);
        void bcm2835_gpio_clr(final char pin);
    }
    public static void main(String[] args) {

        CLibrary.INSTANCE.printf("Hello, World\n");
        for (int i = 0; i < args.length; i++) {
            CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
        }

        System.setProperty("jna.library.path", "/opt/samba/netbeans_project/jna_bcm_1/lib");
        if (BCMLibrary.INSTANCE.bcm2835_init())
        {
          BCMLibrary.INSTANCE.bcm2835_gpio_fsel( PIN, bcm2835.HIGH);
          BCMLibrary.INSTANCE.bcm2835_gpio_set(PIN);
        }
    }

$ java  -jar dist/jna_bcm_1.jar 1 2 3
Hello, World
Argument 0: 1
Argument 1: 2
Argument 2: 3
bcm2835_init: Unable to open /dev/mem: 許可がありません

bcm2835_init()の中でデバイス・ファイル(<==owner root)をオープンしようとして、エラーになりました。orz

bcm2835_init()の処理を調べてみると、/dev/memを読んで制御レジスタのベース・アドレスを設定しています。また、debugモードでは/dev/memを読み込まずに固定値を設定しています。

『しめた!これで行ける。』
        BCMLibrary.INSTANCE.bcm2835_set_debug(bcm2835.HIGH);
        if (BCMLibrary.INSTANCE.bcm2835_init())
        { 以下略

デバッグ・モード設定を追加して動かすと・・・
$ java -jar dist/jna_bcm_1.jar 1 2 3
Hello, World
Argument 0: 1
Argument 1: 2
Argument 2: 3
bcm2835_peri_read paddr 20200004
bcm2835_peri_write paddr 20200004, value 00200000
bcm2835_peri_write paddr 2020001C, value 00020000

bcm2835ライブラリが呼び出されました。ただし、このままでは動作表示するだけで、制御レジスタへのアクセスは行われません。

『ならば、これでどうだ!』
        BCMLibrary.INSTANCE.bcm2835_set_debug(bcm2835.HIGH);
        if (BCMLibrary.INSTANCE.bcm2835_init())
        {
          BCMLibrary.INSTANCE.bcm2835_set_debug(bcm2835.LOW);
          BCMLibrary.INSTANCE.bcm2835_gpio_fsel( PIN, bcm2835.HIGH);
          BCMLibrary.INSTANCE.bcm2835_gpio_set(PIN);
        }

bcm2835_iinit()呼び出しの前後でdebugモードをON/OFFしたところ・・・
$ java  -jar dist/jna_bcm_1.jar 1 2 3
Hello, World
Argument 0: 1
Argument 1: 2
Argument 2: 3
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0xab85d988, pid=7130, tid=3057144944
#
以下省略

”fatal error”になりました。orz

考えてみれば当然です。bcm2835ライブラリの不正なメモリ・アクセス(gpio制御)が許されるをJREが許す訳がありません。基本的な構想に誤りがあります。
------------------
(2013.08.28)
Cで書かれたライブラリのメモリ・アクセスをJVMが監視している訳では無いので記述を訂正しました。
------------------

一旦、退却です。
------------------
(2013.08.29)
mmapとmunmapの意味が少し判ってきました。ユーザ・プロセスのメモリ空間に制御レジスタをマッピングする仕組みだったのですね。
------------------

にほんブログ村 IT技術ブログへ
にほんブログ村 ネットブログ コミュニティサイトへ
にほんブログ村 IT技術ブログ オープンソースへ


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。