VM ポーティング手順マニュアル mrubyポーティング

 mrubyポーティングとは

mruby を特定のシステム上で動作させるためには、 mruby の移植作業 (修正および再構築) が必要となる。この移植作業がポーティングである。 mrubyのポーティングでは、mruby の実⾏基盤である mruby仮想マシン (mruby VM) を 実⾏環境で動作させることが必要となる。 本稿では、mrubyをQSIPボードで動作させるために実施したポーティング作業の概要を示す。

1 mrubyポーティングの概要

 mruby ポーティングの概要 QSIPボードにmrubyをポーティングする手順を以下に示す。 1. mruby ビルド環境の構築 mrubyをビルドするための開発環境を構築する。 本稿ではWindows上にmrubyビルド環境を構築した。

2. QSIP向けのmrubyクロスビルド mrubyをQSIPボード用にクロスコンパイルし、mrubyライブラリ (libmruby.a) を作成 する。 本稿では、 IAR Embedded Workbench for ARM にmruby クロスビルド環境を構 築した。

3. QSIP アプリケーションへの mruby 組み込み QSIPアプリケーションにmruby VM を呼び出す処理 (mruby API) を追加し、 mrubyライブラリ(libmruby.a)をリンクする。

4. QSIP用ライブラリの作成 QSIP ボードに搭載されているデバイスを制御するためのクラスライブラリを作成し、 mruby VMに組み込むことで、mrubyアプリケーションからQSIP搭載デバイスの制御を 可能とする。 5. 2 mrubyビルド環境の構築

Fujitsu3 Kyushu Network Technologies CONFIDENTIAL 環境構築

 ターゲット環境仕様

mruby ポーティングのターゲット環境(QSIP ボード )の仕様を以下に示す。 メイン MPU プロセッサ MK24FN1M0VLL12 ROM 1MB RAM 256KB

サブサブサブ MPU プロセッサ MKL93Z32VFK4 ROM 32KB RAM 2KB

デバイス 外部フラシュメモリ 32MB センサ 磁力、電圧検出、光、温湿度、静電容量、ジャイロ インターフェイス RS232C 、JTAG

4 環境構築

 開発環境仕様

mruby ポーティング作業に使用した環境を以下に示す。

PCPCPC モデル Fujitsu FMVNSS8AE OS Windows 7 Professional (32bit) プロセッサ Intel® Core™ is-3340M CPU (2.7GHz) RAM 4GB

ソフトウェア Cygwin 2.6.1-1 GNU Bison 2.4.1 Ruby 2.3.3 -p222 EWARM 7.80.4

5 環境構築

 Windowsビルド環境構築

Windows 上に mruby ビルド環境を構築する

① C言語ビルド環境(Cygwin)のセットアップ

② Ruby のセットアップ

③ パーサージェネレータ(GNU Bison)のセットアップ

④ mrubyソースコードの入手・mrubyのビルド

⑤ 動作確認

6 Windows ビルド環境 ①ターミナル

 Cygwin ダウンロード編  公式サイトよりインストール •http ://cygwin.com/

クリックして ダウンロード

 参考URL •http://musashi.osdn.jp/cygwin/cygwin.html

7 Windows ビルド環境 ①ターミナル  Cygwin インストール編 任意のフォルダを 指定

末尾 .jp を選択

任意のフォルダを 指定

(次スライドに続く)

8 Windows ビルド環境 ①ターミナル

 Cygwin インストール編 “Category” の “Devel ” を Install にする “binutils” と “bison”、”gcc-core” を 最新バージョン にする

9 Windows ビルド環境 ②Ruby

 Ruby ダウンロード編  公式サイトよりダウンロード •https://rubyinstaller.org/

クリックして ダウンロード

 参考URL •http://www.rubylife.jp/install/install/index1.html

10 Windows ビルド環境 ②Ruby

 Ruby インストール編 任意のフォルダを 指定

11 Windows ビルド環境 ③パーサー

 bison ダウンロード編  公式サイトよりダウンロード •http:// gnuwin32.sourceforge.net/packages/bison.htm

クリックして ダウンロード

 参考URL •http://ameblo.jp/oregano-blog/entry-10400001478.htm

12 Windows ビルド環境 ③パーサー  bison インストール編 任意のフォルダを 指定

13 Windows ビルド環境 ④ビルド

 mruby ソースコード ダウンロード編  GitHub から mruby の最新ソースコードをダウンロード • https://github.com/mruby/mruby

クリックして ダウンロード

 取得リビジョン c48aef0b653ba83452c97b1d1017869de2a846b9  参考URL http://qiita.com/ko2a/items/b29acc616f67738465ea

14 Windows ビルド環境 ④ビルド

 mruby ソースコード ビルド編  ダウンロードした zip ファイル(mruby --master ) を 任意のディレクトリ に解凍する。

 Cygwin を起動し、 解凍先のディレクトリ に移動する。

15 Windows ビルド環境 ④ビルド

 mruby ソースコード ビルド編  コマンドを⼊⼒する ⇒ 下図の画面が表示されたらビルド成功。

16 Windows ビルド環境 ⑤動作確認

 Hello, mruby world !! メイク編  mrubyソース(mrubymruby--mastermaster ) の binbinフォルダフォルダ に 「 Hello.rb 」 を作成する。

ソースコード "Hello.rb"

puts “Hello, mruby world !!”

17 Windows ビルド環境 ⑤動作確認

 Hello, mruby world !! 動作確認編  mrubymruby--master/binmaster/binディレクトリディレクトリ に移動して、 ././mrubymruby HHello.rbello.rb コマンドを⼊⼒する。 ⇒ Hello, mruby world !! と表示されたら成功。

18 QSIP向けのmrubyクロスビルド

Fujitsu19 Kyushu Network Technologies CONFIDENTIAL 環境構築

 mrubyクロスビルド

QSIP 向けクロスビルド環境 IAR Embedded Workbench for ARM を使用して、 mrubyをQSIP向けにクロスビルドする。

① IAR Embedded Workbench for ARM (EWARM) のセットアップ

② mruby のクロスビルド (libmruby.a の作成)

20 mrubyポーティング ①EWARMインストール  IAR Embedded Workbench for ARM ダウンロード編  公式サイトより無償評価版(30日期間限定版)をダウンロード •https://www.iar.com/jp/

クリックして ダウンロード

セットアップ手順については ここ を参照してください

21 mrubyポーティング ②ビルド  クロスコンパイル libmruby.a 作成編  mrubyソース(mrubymruby--mastermaster ) 内の build_config.rb を編集し、 再度 make すると 「 QSIP 」フォルダ配下に libmruby.a が生成される

MRuby::CrossBuild.new('QSIP') do |conf| toolchain :gcc conf.linker.flags << "-m32"

conf.cc do |cc| cc.command='C:/Devz/ARM/LAUNCHPAD/bin/arm-none-eabi-gcc' cc.flags = [] cc.flags << '-mcpu=cortex-m4 -march=armv7e-m -mtune=cortex-m4' cc.flags << '-mthumb -mlittle-endian -mno-unaligned-access' cc.flags << '-mapcs-frame -mno-sched-prolog -mfpu=fpv4-sp-d16 -mfloat-abi=soft ' cc.flags << '-std=gnu99 ' cc.flags << ' -fno -strict -aliasing -fsigned -char' cc.flags << '-ffunction-sections -fdata-sections ' cc.flags << '-fno-schedule-insns2 ' cc.flags << '--param max-inline-insns-single=1000 ' cc.flags << '-nostartfiles -fno-common ' cc.flags << '-fno-hosted' cc.flags << '-gdwarf-2 -O0 -flto-partition=none -fipa-sra' cc.flags << %w(-DMRB_USE_FLOAT)

cc.defines << %w(MRB_HEAP_PAGE_SIZE=8) cc.defines << %(MRB_IREP_ARRAY_INIT_SIZE=128u) cc.defines << %w(MRB_USE_IV_SEGLIST) cc.defines << %w(KHASH_DEFAULT_SIZE=8) cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) #cc.defines << %w(DISABLE_STDIO) #if you dont need cc.defines << %w(MRB_GC_STRESS) #no document cc.defines << %w(POOL_PAGE_SIZE=256) #effective only for use with mruby-eval end

conf.archiver do |ar| ar.command = ‘C:/Devz/ARM/LAUNCHPAD/bin/arm-none-eabi-ar’ end

conf.bins = [] conf.build_mrbtest_lib_only # conf.gem :core => "mruby-print" conf.gem :core => "mruby -math“ # conf.gem :core => "mruby-enum-ext“ # conf.gem '../mruby-direct‘ end

22 mrubyポーティング ②ビルド

 クロスコンパイル libmruby.a 作成編  mrubyソース(mrubymruby--mastermaster ) 内の build_config.rb を編集し、 再度 make すると 「 QSIP 」フォルダ配下に libmruby.a が生成される build_config.rb

MRuby::Build.new do |conf| # end # load specific toolchain settings # mrbc settings # Gets set by the VS command prompts. # conf.mrbc do |mrbc| if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] # mrbc.compile_options = "-g -B%{funcname} -o-" # The -g toolchain :visualcpp option is required for line numbers else # end toolchain :gcc end # Linker settings # conf.linker do |linker| enable_debug # linker.command = ENV['LD'] || 'gcc' # linker.flags = [ENV['LDFLAGS'] || []] # Use mrbgems # linker.flags_before_libraries = [] # conf.gem 'examples/mrbgems/ruby_extension_example' # linker.libraries = %w() # conf.gem 'examples/mrbgems/c_extension_example' do |g| # linker.flags_after_libraries = [] # g.cc.flags << '-g' # append cflags in this gem # linker.library_paths = [] # end # linker.option_library = ' -l%s ' # conf.gem 'examples/mrbgems/c_and_ruby_extension_example' # linker.option_library_path = '-L%s' # conf.gem : => 'masuidrive/mrbgems- # linker.link_options = "%{flags} - example', :checksum_hash => o %{outfile} %{objs} %{libs}" '76518e8aecd131d047378448ac8055fa29d974a9' # end # conf.gem :git => '[email protected]:masuidrive/mrbgems- example.git', :branch => 'master', :options => '-v' # Archiver settings # conf.archiver do | archiver | # include the default GEMs # archiver.command = ENV['AR'] || 'ar' conf.gembox 'default' # archiver.archive_options = 'rs %{outfile} %{objs}' # C compiler settings # end # conf.cc do |cc| # cc.command = ENV['CC'] || 'gcc' # Parser generator settings # cc.flags = [ENV['CFLAGS'] || %w()] # conf.yacc do |yacc| # cc.include_paths = ["#{root}/include"] # yacc.command = ENV['YACC'] || 'bison' # cc.defines = %w(DISABLE_GEMS) # yacc.compile_options = '-o %{outfile} %{infile}' # cc.option_include_path = '-I%s' # end # cc.option_define = '-D%s' # cc.compile_options = "%{flags} -MMD -o %{outfile} - # gperf settings c %{infile}" # conf.gperf do |gperf|

23 mrubyポーティング ②ビルド

build_config.rb (続き )

# gperf.command = 'gperf' # gperf.compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t - MRuby::Build.new('test') do |conf| N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}' # Gets set by the VS command prompts. # end if ENV[' VisualStudioVersion '] || ENV['VSINSTALLDIR'] toolchain :visualcpp # file extensions else # conf.exts do |exts| toolchain :gcc # exts.object = '.o' end # exts.executable = '' # '.exe' if Windows # exts.library = '.a' enable_debug # end conf.enable_bintest conf.enable_test # file separetor # conf.file_separator = '/' conf.gembox 'default' end # bintest # conf.enable_bintest MRuby::Build.new('bench') do |conf| end # Gets set by the VS command prompts. if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] MRuby::Build.new('host-debug') do |conf| toolchain :visualcpp # load specific toolchain settings else toolchain :gcc # Gets set by the VS command prompts. conf.cc.flags << '-O3' if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] end toolchain :visualcpp else conf.gembox 'default' toolchain :gcc end end # Define cross build settings enable_debug # MRuby::CrossBuild.new('32bit') do |conf| # toolchain :gcc # include the default GEMs # conf.gembox 'default' # conf.cc.flags << "-m32" # conf.linker.flags << "-m32" # C compiler settings # conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK) # conf.build_mrbtest_lib_only # # Generate mruby debugger command (require mruby-eval) # conf.gem 'examples/mrbgems/c_and_ruby_extension_example' conf.gem :core => "mruby-bin-debugger" # # conf.test_runner.command = 'env' # bintest # # conf.enable_bintest # end end

24 mrubyポーティング ②ビルド

build_config.rb (続き ) ※ 赤字は追加コード

#add QNET MRuby::CrossBuild.new('QSIP') do |conf| toolchain :gcc

conf.linker.flags << "-m32"

conf.cc do |cc| cc.command='C:/Devz/ARM/LAUNCHPAD/bin/arm-none-eabi-gcc' cc.flags = [] cc.flags << '-mcpu=cortex-m4 -march=armv7e-m -mtune=cortex- m4' cc.flags << '-mthumb -mlittle-endian -mno-unaligned-access' cc.flags << '-mapcs-frame -mno-sched-prolog -mfpu=fpv4-sp-d16 -mfloat-abi=soft ' cc.flags << '-std=gnu99 ' cc.flags << '-fno-strict-aliasing -fsigned-char' cc.flags << '-ffunction-sections -fdata-sections ' cc.flags << ' -fno -schedule -insns2 ' cc.flags << '--param max-inline-insns-single=1000 ' cc.flags << '-nostartfiles -fno-common ' cc.flags << '-fno-hosted' cc.flags << '-gdwarf-2 -O0 -flto-partition=none -fipa-sra' cc.flags << %w(-DMRB_USE_FLOAT) cc.defines << %w(MRB_HEAP_PAGE_SIZE=8) cc.defines << %(MRB_IREP_ARRAY_INIT_SIZE=128u) cc.defines << %w(MRB_USE_IV_SEGLIST) cc.defines << %w(KHASH_DEFAULT_SIZE=8) cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) #cc.defines << %w(DISABLE_STDIO) #if you dont need cc.defines << %w(MRB_GC_STRESS) #no document cc.defines << %w(POOL_PAGE_SIZE=256) #effective only for use with mruby-eval end

conf.bins = [] conf.build_mrbtest_lib_only # conf.gem :core => "mruby-print" # conf.gem :core => "mruby-math" # conf.gem :core => "mruby-enum-ext" # conf.gem '../mruby-direct' end

25 QSIPアプリケーションへの mruby組み込み

Fujitsu26 Kyushu Network Technologies CONFIDENTIAL  QSIPアプリケーションへのmruby組み込み

QSIP 用の C言語アプリケーションに mruby ライブラリ (libmruby.a )および mruby アプリケー ションをリンクする。

① EWARM 設定

1. QSIPアプリケーションへのmrubyソースコードの追加

2. インクルードディレクトリに mruby のインクルードパスを追加

3. リンカ設定でmrubyライブラリ (libmruby.a) を追加

② mruby 動作確認用アプリケーションの作成

27 mrubyポーティング ②ビルド  EWARMへのmruby ソースコード追加  EWARM の ワークスペース > ファイル(既存ソースコード ) に mruby ソースコードを追加する

28 mrubyポーティング ②ビルド  EWARMインクルードディレクトリの追加  EWARM の プロジェクト > オプション > カテゴリ :C,C++ コンパイラ > タブ :プリプロセッサ より、追加インクルードディレクトリに mruby ヘッダソースのパスを追加

29 mrubyポーティング ②ビルド  EWARMのリンカ設定  EWARM の プロジェクト > オプション > カテゴリ:リンカ > タブ:ライブラリ より 前スライドで生成したライブラリ(libmruby.a )のパスをリンカに追加する

30 mrubyポーティング ③動作確認  mruby 動作確認用のアプリケーション作成  下記のソースコードを作成してQSIPアプリケーションをビルドし、アプリケーションを含 むファームウェアを QSIP ボードに書き込んで実⾏する。 QSIPアプリケーションからmruby VMが起動できていることを確認する。

#include "mruby.h" #include

void main(void) { printf(“mrb_open¥n”); // mruby 仮想マシンの作成 mrb_state *mrb = mrb_open ();

printf(“mrb_close¥n”); // 仮想マシンを閉じる mrb_close (mrb );

printf(“finish¥n”); }

31 QSIP用ライブラリの作成

Fujitsu32 Kyushu Network Technologies CONFIDENTIAL  QSIPアプリケーションへのmruby組み込み

QSIP ボード用の mrbgems (mruby クラスライブラリ )を作成し、 libmruby.a にライブラリを 追加する。

① mrbgems 作成

② mruby VMへのmrbgems追加

③ mruby 動作確認用アプリケーションの作成

33 mrubyポーティング ④ライブラリ化

 mrbgems 作成  mruby-master¥mrbgems以下に下記ディレクトリ、ファイルを作成する.

mruby-master¥ mrbgems¥ sample_qsip ¥ mrbgem.rake 作成対象 src ¥ sample_qsip.c

34 mrubyポーティング ④ライブラリ化  mrbgems 作成  mruby-master¥mrbgems¥sample_qsip¥mrbgem.rake

MRuby::Gem::Specification.new('sample_qsip') do |spec| spec.license = 'MIT' spec.author = 'QNET' spec.summary = 'QSIP sample library' end

35 mrubyポーティング ④ライブラリ化  mrbgems 作成  mruby-master¥mrbgems¥qsip_sample¥src¥qsip_sample.c

#include "mruby.h" #include

// ライブラリ化する処理 static mrb_value mrb_sample_qsip(mrb_state *mrb, mrb_value self) { puts("mruby on QSIP"); // 文字列を表示 return mrb_nil_value(); // nil を返す }

void mrb_sample_qsip_gem_init(mrb_state* mrb) { // Sample_QSIP モジュールの登録 struct RClass *class_sample_qsip = mrb_define_module(mrb, “Sample_QSIP"); // sample_qsip メソッドの登録 mrb_define_class_method(mrb, class_sample_qsip, “sample_qsip", mrb_sample_qsip, ARGS_NONE()); }

void mrb_sample_qsip_gem_final (mrb_state * mrb ) { }

Sample_QSIP :: sample_qsip メソッドとして実装した。

36 mrubyポーティング ④ライブラリ化

 mruby VMへのmrbgems 追加 MRuby::CrossBuild.new('QSIP') do |conf| toolchain :gcc  build_config.rb に conf.linker.flags << "-m32"

conf.cc do |cc| 作成した mrbgems を追記し、 cc.command ='C:/ Devz /ARM/LAUNCHPAD/bin/arm -none -eabi -gcc ' cc.flags = [] 再度 cc.flags << '-mcpu=cortex-m4 -march=armv7e-m -mtune=cortex-m4' make する。 cc.flags << '-mthumb -mlittle-endian -mno-unaligned-access' cc.flags << '-mapcs-frame -mno-sched-prolog -mfpu=fpv4-sp-d16 -mfloat-abi=soft ' cc.flags << '-std=gnu99 ' cc.flags << '-fno-strict-aliasing -fsigned-char' cc.flags << ' -ffunction -sections -fdata -sections ' build ¥QSIP ¥lib フォルダ 配下には cc.flags << '-fno-schedule-insns2 ' cc.flags << '--param max-inline-insns-single=1000 ' cc.flags << '-nostartfiles -fno-common ' 作成した mrbgems が追加された cc.flags << '-fno-hosted' cc.flags << '-gdwarf-2 -O0 -flto-partition=none -fipa-sra' libmruby.a が生成される cc.flags << %w(-DMRB_USE_FLOAT) cc.defines << %w(MRB_HEAP_PAGE_SIZE=8) cc.defines << %(MRB_IREP_ARRAY_INIT_SIZE=128u) cc.defines << %w(MRB_USE_IV_SEGLIST) cc.defines << %w(KHASH_DEFAULT_SIZE=8) cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) #cc.defines << %w(DISABLE_STDIO) #if you dont need cc.defines << %w(MRB_GC_STRESS) #no document cc.defines << %w(POOL_PAGE_SIZE=256) #effective only for use with mruby-eval end

conf.archiver do |ar| ar.command = ‘C:/Devz/ARM/LAUNCHPAD/bin/arm-none-eabi-ar’ 作成した end conf.bins = [] mrbgems conf.build_mrbtest_lib_only conf.gem :core => "mruby-print" を追記 # conf.gem :core => "mruby-math“ # conf.gem :core => "mruby-enum-ext“ conf.gem :core => " mruby -sample -qsip “ # conf.gem '../mruby-direct‘ end

37 mrubyポーティング ④ライブラリ化  mrbgems 動作確認用のアプリケーション作成  下記のソースコード (app.rb) を作成する。 puts "mruby application start." Sample_QSIP::sample_qsip # mrbgems のメソッド呼び出し puts "mruby application end."

 mruby コンパイラ (mrbc ) でコンパイルする。 mrbc –Bappbin –o./app.c app.rb

出⼒された app.c はアプリケーションプロジェクトに追加する。

38 mrubyポーティング ④ライブラリ化  mrbgems 動作確認用のアプリケーション作成  下記のソースコードを作成して、mrbgems組込み済みのlibmruby.aとリンクして QSIP アプリケーションを作成する。アプリケーションを含むファームウェアを QSIP ボード に書き込んで実⾏する。 QSIPアプリケーションからmrbgemsのメソッドが呼び出されることを確認する。

#include "mruby.h" #include "mruby/irep.h" #include

void main(void) { extern uint8_t appbin[]; // app.c のアプリケーションバイナリを外部参照する mrb_state *mrb = mrb_open(); printf ("mruby VM opened. ¥n");

mrb_load_irep(mrb, appbin); // mruby アプリケーション実⾏ printf("mruby application done.¥n");

mrb_close (mrb ); printf("mruby VM closed.¥n"); }

39