PICrouterでmruby v1.0.0を使うために(2/23更新)

備忘録という意味合いが強いけど、いつの間にかmruby 安定版 v1.0.0がリリース
されていたこともあり、以前、PICrouterのwikiにメモした内容をこのv1.0.0向けに
手直しして書きます。
 

0.注意

mrubyでrubyに触り始めた初心者が書いていますので、訂正や助言頂けると嬉しいです。
 

1.準備

PICrouterでmrubyするために必要なものは次の通り。
 
wikiにも書いてありますが、mrubyでOSCやるのにオリジナルのPICrouterでは
さすがに厳しいです。MPLABXは特にバージョン指定ありませんし、特にIDEに
バグも無いので最新版で良いと思います。XC32コンパイラはフリー版でOKです。
ただし、v1.30とv1.31はPIC32のUSB HIDブートローダーとの兼ね合いでコンパイル
がこけるので、この問題が修正されるまではv1.22を使って下さい。どうしても、
v1.31が使いたいって人はこの辺を参考に自力対処して下さい。
あと、私の場合は、CygwinとVisual Studio Express 2013がインストール済みです。
 
mruby-1.0.0に併せて、mruby用のプロジェクトを更新し、mrubyから使うCの関数を
追加したりしたv0.2.1をgithubで公開してます。ソースは見づらいかもしれませんが、
少しずつ整理していきますので・・・。

2.build_config.rbの書き換え

まず、PICrouter用のlibmruby.aを作ります。そのために、mruby-1.0.0フォルダの
中にある「build_config.rb」にPICrouter用の記述を追加する必要があります。
まずは、末尾に以下を追記します。PATHは自身の環境に合わせて下さい。
また、これまではmrbconf.hを直接編集していましたが、ここでcc.definesを使う
ように変更しました。この方法が推奨のようです。
MRuby::CrossBuild.new("PICrouter") do |conf|
  toolchain :gcc

  PICROUTER_PATH = "C:/Users/shun/MPLABXProjects/PICrouter"
  XC32_PATH = "C:/Program Files (x86)/Microchip/xc32/v1.22"
  MRUBY_PATH = "C:/Users/shun/MPLABXProjects/PICrouter/mruby-1.0.0"

  conf.cc do |cc|
    cc.command="#{XC32_PATH}/bin/xc32-gcc.exe"
    cc.include_paths = ["#{PICROUTER_PATH}/PICrouter_795_mrb.X",
                        "#{PICROUTER_PATH}/PICrouter_795_mrb.X/Include",
                        "#{PICROUTER_PATH}/PICrouter_795_mrb.X/USB",
                        "#{MRUBY_PATH}/include",
                        "#{XC32_PATH}/pic32mx/include"]
    cc.flags << "-g -ffunction-sections -fdata-sections -mips16 -mprocessor=32MX795F512H -O1 -Wl,--defsym=__MPLAB_BUILD=1," +
      "-Map=\"dist/default/production/PICrouter_795_mrb.X.production.map\",--defsym=_min_heap_size=102284,--defsym=_min_stack_size=1136,--gc-sections,"
    cc.compile_options = "%{flags} -o %{outfile} -c %{infile}"
    
    cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
    cc.defines << %w(MRB_USE_IV_SEGLIST)
    cc.defines << %w(MRB_IVHASH_INIT_SIZE=3)
    cc.defines << %w(KHASH_DEFAULT_SIZE=8)
    cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
    cc.defines << %w(MRB_GC_STRESS)
    #cc.defines << %w(DISABLE_STDIO)

  end

  conf.cxx do |cxx|
    cxx.command = conf.cc.command.dup
    cxx.include_paths = conf.cc.include_paths.dup
    cxx.flags = conf.cc.flags.dup
    cxx.defines = conf.cc.defines.dup
    cxx.compile_options = conf.cc.compile_options.dup
  end

  conf.archiver do |archiver|
    archiver.command = "#{XC32_PATH}/bin/xc32-ar"
    archiver.archive_options = 'rcs %{outfile} %{objs}'
  end

  #no executables
  conf.bins = []

  #do not build test executable
  conf.build_mrbtest_lib_only

 end
mruby-1.0.0/examples/targetsフォルダの中のコードを参考にして、githubに
PICrouter.rbを作ってアップしておきました。
 

3.IncludeするGemの選択

2の記述を追加して、make clean & makeすれば、libmruby.aは出来上がります。
ただ、PIC32MX795F512HもRAMが128kしかないので、mruby本体にメモリを
圧迫され、自前のコードのためのスペースが少なくなってしまいます。なので、
PICrouterで使わないであろうGemのインクルードを止めることにします。
mruby-1.0.0/mrbgemsの中に「default.gembox」というのがあり、さきほどの
「build_config.rb」内で、「conf.gembox 'default'」としてあります。ここで、必要な
Gemのインクルードを記述をしているようです。なので、これを複製して、
picrouter.gemboxとファイル名を変更、mruby-timeなど不要なGemをコメント
アウトします。
 
MRuby::GemBox.new do |conf|
  # Use standard Kernel#sprintf method
  #conf.gem :core => "mruby-sprintf"

  # Use standard print/puts/p
  #conf.gem :core => "mruby-print"

  # Use standard Math module
  conf.gem :core => "mruby-math"

  # Use standard Time class
  #conf.gem :core => "mruby-time"

  # Use standard Struct class
  #conf.gem :core => "mruby-struct"

  # Use extensional Enumerable module
  conf.gem :core => "mruby-enum-ext"

  # Use extensional String class
  conf.gem :core => "mruby-string-ext"

  # Use extensional Numeric class
  conf.gem :core => "mruby-numeric-ext"

  # Use extensional Array class
  conf.gem :core => "mruby-array-ext"

  # Use extensional Hash class
  conf.gem :core => "mruby-hash-ext"

  # Use extensional Range class
  conf.gem :core => "mruby-range-ext"

  # Use extensional Proc class
  conf.gem :core => "mruby-proc-ext"

  # Use extensional Symbol class
  conf.gem :core => "mruby-symbol-ext"

  # Use Random class
  conf.gem :core => "mruby-random"

  # Use extensional Object class
  conf.gem :core => "mruby-object-ext"

  # Use ObjectSpace class
  #conf.gem :core => "mruby-objectspace"

  # Use Fiber class
  #conf.gem :core => "mruby-fiber"

  # Use extended toplevel object (main) methods
  conf.gem :core => "mruby-toplevel-ext"

  # Generate mirb command
  #conf.gem :core => "mruby-bin-mirb"

  # Generate mruby command
  #conf.gem :core => "mruby-bin-mruby"
end
これもgithubに、picrouter.gemboxとしてアップしておきました。「build_config.rb」の
「conf.gembox 'default'」を「conf.gembox 'picrouter'」と書き換えて使用します。
 

4.メモリ節約のための記述

加えて、mruby-1.0.0/include/mruby/value.hの275行目付近
typedef struct mrb_value {
  union {
    mrb_float f;
    void *p;
    mrb_int i;
    mrb_sym sym;
  } value;
    enum mrb_vtype tt;
} mrb_value;
となっている箇所を
typedef struct mrb_value {
  union {
    mrb_float f;
    void *p;
    mrb_int i;
    mrb_sym sym;
  } value;
    enum mrb_vtype tt:8;
} mrb_value;
とします。以前は、ここをさらに「#pragma pack(1)」で詰めていましたが、これをすると
C側でmrb_funcallを呼び出したときに動作が停止してしまいました。pack()するときは
環境やコンパイラのバージョンなどに注意した方が良いかもしれません。
また、mruby-1.0.0/src/symbol.cの14行目付近
typedef struct symbol_name {
  mrb_bool lit;
  uint16_t len;
  const char *name;
} symbol_name;
#pragma pack(1)
typedef struct symbol_name {
  mrb_bool lit;
  unsigned char len;
  const char *name;
} symbol_name;
#pragma pack()
とします。これらは前回同様にkyabさんのブログを参考にさせて頂きました。
これで、「make clean & make」でmruby-1.0.0/build/PICrouter/libの中に
libmruby.aの出来上がりです。
 
これをMPLABX上でmruby用のプロジェクトの「Libraries」に加え、Project
PropertiesのCategories→「xc32-gcc」、Option categories→「Preprocessing
and  messages」にある「Include directories」にmruby-1.0.0/includeを加えて
下準備は完了です。
 
Cのコードとmrubyのコードを用意して、ゴニョゴニョできるようになりました。

コメントをどうぞ

Your email address will not be published. Required fields are marked *

*