mruby/cで複数のtask

mruby/cでは複数のtaskを走らせることができる。 その機能を使ったことはこれまで無かったが、折角使えるので使い方を考えてみた。 私が構築しているシステムでは、mrbのコードはflashの特定のアドレス以降に書いておいて、そこを書き換えることによって、mrbだけを入れ替えることができるようにしている。 そこに複数のmrbコードを並べて、それらを読み込んで実行できるようにすれば良いだろう。 一つのmrbのすぐ後に、またmrbのコードがある場合には、それを次のtaskとして登録するようにするのである。 そのための関数は以下のように定義することができる。

void load_continuous_tasks(const uint8_t *start_addr) {
  for (int i = 0; MAX_VM_COUNT > i ; i++) {
    if (memcmp(start_addr, "RITE", 4) != 0) break;
    mrbc_create_task(start_addr, 0);
    start_addr += // big endian
      ((uint32_t)start_addr[8]  << 24) |
      ((uint32_t)start_addr[9]  << 16) |
      ((uint32_t)start_addr[10] <<  8) |
      ((uint32_t)start_addr[11] );
  }
}

試しに、GPIOを使うmrbと、printを使うmrbを同時に走らせてみたら、問題なく動いた。 変数などはそれぞれのtaskで独立のようだ。 グローバル変数を使うと、taskを越えて使えるそうだが、まだ試していない。 マイコンでマルチタスクを使ったことは無いので、どう使うと便利なのかも考えてみたい。

Read more...

基板設計の半自動化

最近はマイコンとして、安価なCH32シリーズに注目している。 中でも比較的性能の高いCH32V203を使う機会が多くなってきている。 しかし、CH32V203のマイコンボードで入手しやすいblue pill+は比較的大きいので、pro micro程度の小型のものを欲しいと思っている。 そのようなものも販売されているが、部品の価格と比べて、かなり高額なものしか見当たらない。 そこで、自分でボードを設計しようかとも思うのだが、いくつか課題がある。 一つは回路を設計するのが面倒であるという点であり、もう一つはボードを注文すると個人で使うには過大な枚数になってしまうという点である。 設計が面倒だという点については、AIと配線の自動化を使うと解決できるということを知ったので、これを試してみた。

まず、AIにボードのピンとマイコンのピンの割り当てを考えてもらう。 そして、それに基いてkicad用のネットリストを作ってもらう。 pro microの端子にSWD用の端子を付け加えると、32pinのCH32V203K8T6の場合、外部振動子を除くと、一つだけピンが余るので、それをLEDに割り当てることができた。 最初は、kicadで読み込むとエラーは出ないが何も表示されなくて苦労したが、version Eということを指定して作ってもらったら、うまく行った。 必要なら、部品のパッケージなどを変更するように指定すると良いだろう。

それをkicadのpcb editorでファイル-インポート-ネットリストとして読み込むと部品が表示される。 部品の配置は、人間がやらないといけない。 配置も自由度がそれなりにあり、悩むところなのだが、マイコンのICを配線が単純になるような向きに置くことが最も重要で、それ以外の部品は、使い易い位置にすれば良いだろう。 USBの二本のデータ線は、同じ長さにしなければならないので、他の配線の邪魔にならないように意識しながら、あらかじめ配線しておく。 また、忘れないように、基板の外形を描く。 そして、Specctra DSN形式でエクスポートする。

次に、Freeroutingを実行して、DSNファイルを開いて、自動配線をする。 配線が無事に終ったら、ses形式でセーブする。 うまく配線が出来無い場合には、kicadに戻って部品の配置やUSBの配線などを改良してから、自動配線を試みる。 sesファイルをkicadにSpecctraセッションとしてインポートすると、配線が取り込まれる。 無駄な部分を修正するために、ツール-配線とビアをクリーンアップとする。 配線が不用意に蛇行したりすることもあるので、配線を選択してDを押してから、場所を調整すると良い。 これで、ボードの設計は終了である。

確かに、全部自分でやるよりは、かなり楽になった。 部品の配置は考えないといけないが、これは人によって好みが異なるので、完全な自動化は難しいだろう。 このやり方は初めてだったので、今回は多少の試行錯誤が必要だったが、次に似たような基板を設計する時には、比較的短時間でできると思う。 次に問題なのは、このボードのPCBを注文するかどうかである。

Read more...

ESP32用のmruby/c

ESP32用のmruby/cとしては,FemtoRubyを使ったR2P2があるが,PWMを使おうとしたらエラーが出たので,自分でもESP32用にmruby/cの環境を作ってみることにした. 自分のブログを見直してみたら,私がmruby/cを最初に使ってみたのはESP32だった. そのときには,Arduinoを使ってmrbのコードをソースに埋め込んでコンパイルしていた. そのため,rubyのコードを変えると,mrbを作って,それを埋め込んでArduinoでコンパイルして,マイコンに書き込むという作業をする必要があり,時間もかかるし面倒だった. これまで,何種類かのマイコン用にmruby/cの環境を作ってきた. それらにおいては,mrbファイルはflashに書き込んで,そのアドレスを使って直接mrbコードを読み出して使っている. しかし,同じことをESP32でやろうとしたら,そのままではうまく行かなかった. ESP32では,フラッシュに直接アドレスが割り当てられるわけでは無く,その内容が使われるときにcacheにコピーされるので,単にflashに書き込むだけでは駄目である. また,mrbコードをプログラムに埋め込んでおいて,その部分だけを書き換えようとしても,チェックデジットや誤り訂正などがあり,その内容を不用意に書き換えるとエラーが出てしまった. いろいろ試行錯誤した結果,使っていないflash領域にmrbを書き込んで,それをメモリに割り当てることで,ほぼ同じ感覚で使えるようになった. まず,私のホームページに載っているようにArduino用のmruby/cをセットアップする. そして,Arduinoで以下のコードをコンパイルして,ESP32に書き込む. #include "spi_flash_mmap.h" #include <mrubyc.h> #define MEMORY_SIZE (1024*30) static uint8_t memory_pool[MEMORY_SIZE]; #define FLASH_CODE 0x10000 + 0x120000 //esp32 spi_flash_mmap_handle_t s_data_map_handle; const uint8_t *flash_code = NULL; int hal_write(int fd, const void *buf, int nbytes) { Serial.write((char*)buf,nbytes); return (nbytes); } int hal_flush(int fd) { return 0; } void hal_abort(const char *s){} unsigned char hal_read(int fd) { while (Serial.available() == 0); return Serial.read(); } void setup() { uint32_t data_flash_offset = FLASH_CODE; // running->address + 1114112; uint32_t map_size = 0x10000; // 64KB esp_err_t err = spi_flash_mmap( data_flash_offset, map_size, SPI_FLASH_MMAP_DATA, // as rodata (const void **)&flash_code, &s_data_map_handle); Serial.
Read more...

ESP32でFemtoRuby

以前、raspberry pi picoでPicoRubyを動かしてみたことがあるが、その時にはESP32では動かす方法が見付からなかった。 ESP32では、mruby/cベースのFemtoRubyを使うらしく、それを簡単に使う方法を見付けたので、少し試してみた。 以前はPicoRubyと読んでいたものを、FemtoRubyと呼ぶことにしたらしく、名前が混在していてよく分からないこともある。

ESP32への書き込みは、 Webインストーラー を使って行う。Chromiumでこのサイトに行って、ESP32を繋いで書き込みを行う。 Webからこんなことが出来るようになっているのかと関心した。 別のモジュールで試したら、書き込みに失敗したりしたけど、うまくいったやつで、少し使ってみた。 書き込みは53%から一気に100%になって、不安だったが大丈夫のようだ。

今度は<a href=“https://picoruby.org/terminal>Webターミナルに行って、connectを押してから、リターンキーを何度か押したら、Shellが立ち上がった。 irbと打ったらrubyが使えるようになる。 GPIOを使ってみたら、無事に動いた。 次はADCかなと思ったら、require ‘adc’としないといけないようだ。 その次はPWMを試したら、require ‘pwm’まではできたが、PWM.newしたら、エラーでリセットがかかってしまった。

使えないボードがあったり、エラーでリセットがかかったりと、まだ不安定なようだが、手軽に使えるようになって来ているようだ。 私もESP32でArduinoを使ってmruby/cを動かしているが、その情報を公開する価値があるかどうか迷っている。 ESP8266でmruby/cを使っている人はあまりいないようで、情報が少かったので、このブログにも書いたこともあるし、ホームページにもまとめておいたので、誰かが使ってくれるかも知れない。

Read more...

ch32funのMakefile

ch32funで作ったプログラムのmapファイルを見ていたら,使っていないはずの関数が残っていたので,なんでだろうと思って調べてみたら,Makefileのオプションの指定が間違っていたことが分かった.

別のフォルダにあるライブラリも含めないといけなかったので,それをMakefile中のCFLAGSで指定し, さらに最適化して使っていない関数を除去しようと,以下のように指定していた.

CFLAGS += -Os -flto

理由はよく理解していないが,さらに以下のオプションを加えないと,使っていない関数が適切に除去できなかった.

CFLAGS += -ffunction-sections -fdata-sections

ch32funのexampleの多くでは,これらのオプションの指定はしていない. 調べてみると,ch32fun.mkの中では,以下のような記述がある.

CFLAGS?=-g -Os -flto -ffunction-sections -fdata-sections -fmessage-length=0 -msmall-data-limit=8 -fno-tree-loop-distribute-patterns

しかし,Makefile中でCFLAGSの設定したことによって,この設定が無効になってしまったようだ. Makefileで,ライブラリについての情報はEXTRA_CFLAGSに書くようにして,CFLAGSを指定しないしないようにしたら,期待通りの結果が得られた.

Read more...

mruby/cの表示ルーチンの改良

mruby/cには,表示をするやり方が複数ある. ruby側からは,p,puts,print,printfなどがあり, C言語からもいくつもの表示方法がある. ruby側から表示する関数は,c_object.cの中で定義されているが, p,puts,printでは,対応するC言語側の関数を呼び出しているのに対して, printfはsprintfを通して,mrbc_printf_intやmrbc_printf_floatを呼び出している. C言語から表示する関数は,console.cの中で定義されており, mrbc_print,mrbc_printfなどを使って表示することになっているが, 整数の場合にはmrbc_printf_intで, 浮動小数の場合にはmrbc_printf_floatとmrbc_format_floatで整形されている. 整数を扱うmrbc_printf_intでは,整数を適切に整形するプログラムが書かれているが,負の数でゼロ埋めをする際の処理に軽微なバグがあることを,2026/6/29のブログで紹介した. 一方,浮動小数を扱うmrbc_printf_floatとmrbc_format_floatでは, 共に整形の部分はsnprintfに丸投げしている. この関数は,非常にコンパイルサイズが大きく,mruby/cにFloatを組み込んだときに大きくなる一つの要因になっていると思われる. 小数はC言語のライブラリを使って整形しているのに,整数はmruby/cでコード書いているのは,Floatを無効にしたときに,整数を整形できるようにするためであろうが,Floatを使う際には整数の整形ルーチンがダブってしまい,無駄が多い. そこで,小数の整形をするルーチンを独自に書き下して,snprintfを使わないようにすれば,Floatを組み込む際にも,それほど大きくならないように出来るかも知れない. また,ch32funのsnprintfでは小数は表示できないので,Floatの表示ができないが,その問題も解消できる. mrbc_format_floatは,value.cの中で定義されているが, その中のsnprintfはmrbc_snprintfに変更することができる. console.cの中で定義されているmrbc_printf_floatは, mrbc_snprintfで使われているので, 元の関数はmrbc_format_float2と名前を変えて, mrbc_printf_floatを新たに定義することにした. Floatの表示は,通常の小数表記,科学的な表記,自動判定の3つの方法があり,これらはそれぞれ’f’,’e’,‘g’で表され,大文字を使う’E’と’G’もある. これらの表示をするためには,どのような処理が必要かを考えると,整数部と小数点以下を分離して桁数などに応じての表示と,指数部と仮数部の計算などをしなければならないことが分かる. 指数部は,自動判定時の小数表記と科学的表記の分岐にも使われる. そこで,通常の小数を表示する関数と,指数部と仮数部を計算してそのまま科学的表記をするか先の関数を呼び出して小数の表示をする関数の2つの関数を定義し,mrbc_format_floatからは指定に応じてこれらの2つの関数を呼び出すことにした. 通常の小数を表示する関数では,絶対値に直してから,その整数部分と精度を考慮した小数部を,整数として求めて,小数点を挟んでそれらをそれぞれmrbc_printf_intを用いて表示すれば良い. 前者は必要なら符号も表示し,後者は精度の幅でゼロ埋めして表示する. この関数は,科学的な表記の仮数部分を表示するときに呼び出すが,四捨五入で繰り上がりが生じて桁が変わる場合には,仮数を桁を調整しなければならないので,科学表記のときにはそのための処理も行うようにした. この関数を定義するときに,できるだけサイズを小さくするために,効果が大きな2つの工夫を行った. 1つ目の工夫は整数部と小数部に分ける際に,小数点の位置を精度の分だけ下にずらしてから四捨五入のために0.5を足した後で,うまくその2つの部分を取り出したことである. 単精度のときには,全体を整数に変換して,その上位の整数部と下位の小数部を割り算を用いて計算すると,32bitのCPUで扱いやすく,サイズを抑えることができた. 倍精度のときには,整数部は小数点の位置を戻して整数化して取り出し,小数部は整数部の桁数をずらして引くことによって取り出すと,小さくすることができた. 両者で小さくなるようなアルゴリズムが違うのは奇妙な気もする. しかしこのやり方では,整数部や精度が大き過ぎる場合には,問題が起こる可能性もあることに注意が必要である. 2つ目の工夫は,符号と絶対値を求める際に,専用の関数を使ったことである. 単にx<0や-xを計算するだけなら,バイナリでも単純になると思っていたのだが,doubleでは複雑な処理が行われるらしく,math.hを組み込んで,signbitとfabsを使うことで,100バイト以上小さくなった. 指数部の計算などをする関数では,絶対値に直してから,仮数xが1<=x<10になるまで,10を掛けたり割ったりして,同時に指数部を数える. そして,表示方法を自動判定するときには,精度と指数から判定して,小数表記なら先の関数を呼び出して,科学表記なら仮数を同様に表示して指数部は整数として表示する. この関数でも,doubleの処理の部分を工夫することが重要である. 絶対値を取る部分は,先と同様にも処理できるが,1.0や10.0との比較する部分を小さくするために,doubleをuint64_tとして解釈して,処理することにした. 正の数の場合には,doubleの大小とuint64_tの大小が一致することを利用して,大小を判定した方が,コンパイルサイズが小さくなったので,そのようにすることにした. それに伴って,絶対値や符号の処理はbit演算で表した. ソースの可読性が下がるという欠点はあるが,コンパクトにするためには仕方ないだろう. これで,浮動小数点も表示できるようになったが, 精度を指定しなかったときには,それが0になるようになっており, そうすると,printf “%f”,3.14としても,3しか表示さらなくなってしまった. 精度が0のときには,6にするようにすると,今度は精度を0にできなくなってしまう. そこで,精度を指定しなかったときの値を-1にした. そのために,関数mrbc_printf_mainの中でpf->fmtが初期化された直後に-1を代入する. pf->fmt.precision=-1; そして,ピリオドがあったら,その値を0にして,精度を取り込む. pf->fmt.precision=0; しかし, pf->fmt.precisionが0で無い場合に,精度が定義されているという判断をしている箇所が, mrbc_printf_bstrとmrbc_printf_intの中に見つかったので, それらの条件を以下のように書き換えた. pf->fmt.precision > 0 この修正により,デフォルトの表示の精度の問題も無くなり,思った通りに表示できるようになった. snprintfを使っていた場合には,フォーマットの文字列もこの関数で処理されるので,この問題は生じていなかったのである. console.cにこれらの修正をした後に,その末尾に先に考えた以下のコードを追加すれば, 新たなmrbc_print_floatが定義される. #if MRBC_USE_FLOAT #include <math.h> static void mrbc_printf_f(mrbc_printf_t *pf, double value, int *exponent) { int is_negative = signbit(value); value=fabs(value); int precision = pf->fmt.
Read more...

ch32funのfsusb

WCH社のマイコンでmruby/cを使うときなどに、ch32funを使っているのだが、 いつの間にかUSB部分のファイルが更新されたようだ。 github上のプログラムを利用するときには、できるだけreleaseを使うようにしており、そうするとファイルの内容は変更されない。 しかし、ch32funについては、最新のreleaseが一年半以上前のもので、CH32X035などの新しいマイコンを使うこともあるので、github上の最新のファイルを使っている。 普段は、以前downloadしているzipを使って作業をしていたので気付かなかったが、新たにdownloadしたら私のプログラムがコンパイル出来無くなっていたので、原因を調べたら、私が参照しているファイルが更新されたことが原因だった。

CH32X035でUSBを使うために、ch32funのfsusbを使っている。 このファイルは二週間前に更新されており、その仕様が変更になった。 以前と同じようにコンパイルしたら、fsusbで定義されている関数が参照できないというエラーが出て、原因が分からずにしばらく苦労していたが、 ADDITIONAL_C_FILESで指定しないといけなくなったことに気が付いた。 さらにエラーが出たが、それは変数や関数の名称が変更になっていたためであることも分かった。 これらに対応して、修正を加えたら、コンパイルは通るようになった。 追って、動作確認をしてみようと思う。

プログラムを安定して使うためには、やはりreleaseを使った方が良いことを実感したが、ch32funの新しいreleaseが早く出ないかな。

Read more...

ArduinoでCH32V203の隠しflash

CH32V203は、公式のflashは64kであるが、低速のflashが160kあり、 Arduinoからこれを利用する方法は2026/5/17のブログに書いたが、その手法は少し手間がかかった。 それを少し簡単にする方法を見出したので、紹介したい。 まず、160kのflashの情報をLink.ldに記述するのだが、ch32funでの記述を参考にして、EXTという名称にすることにした。 そして、EXTにはrodataを格納することにする。 そのように変更するためのシェルスクリプトは以下の通りである。 cd ~/.arduino15/packages/WCH/hardware/ch32v/1.0.4/system/CH32V20x/SRC/Ld/ sed -i -e 's/\r/\n/g' Link.ld sed -i -e 's@FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K@FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K\n\tEXT (rx) : ORIGIN = 0x08010000, LENGTH = 160K@' -e '/[.]rodata/d' -e 's@\.fini @.storage :\n{\n. = ALIGN(4);\n*(.rodata)\n*(.rodata*)\n. = ALIGN(4);\n} >EXT AT>EXT\n\n\t.fini @' Link.ld 以前に紹介した方法では、スケッチをコンパイルした後で、 通常のflashとEXTに書き込むバイナリを取り出す必要があったのだが、 platform.txtをいじると、これを自動で出来るようにすることができる。 バイナリを保存するように指定したときに、flashとEXTについて、バイナリを取り出して64kになるようにして、スケッチのあるフォルダにコピーするように、するのである。 その設定のためのシェルスクリプトは以下の通りである。 cd ~/.arduino15/packages/WCH/hardware/ch32v/1.0.4/ sed -i -e 's@recipe.objcopy.bin.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.elf2bin.flags} {compiler.elf2bin.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"@recipe.objcopy.bin.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.
Read more...

mruby/cでタイムスタンプを取得

mruby/cを用いて、ある信号のモニタをしようと思ったのだが、それには時間に対して信号がどうなっているのかを記録する必要があった。 しかし、mruby/cでは、sleepなどはできるが、現在の時間を取得することはできない。 arduinoだと、micros()で起動してからの時間がマイクロ秒単位で取得できるのだが、これに相当する機能をmruby/cに実装することにした。

まず、methodの名前をどうするかを悩んだが、ticks_usとすることにした。 mruby/cの整数はdefaultでは32bitなので、一時間と少しで零に戻ることになるが、通常は問題無いだろう。 整数を64bitにもできるが、メモリを食うので、 32bitのままで使うことにした。 ch32funでこれを実現するには、micros()に対応する関数は無いが、クロックを数える関数があるので、何クロックがマイクロ秒に対応するかを考えれば良い。 mruby/c用に、ch32funでマイクロ秒単位のタイムスタンプを返す関数を以下のように定義した。

static void c_ticks_us(mrbc_vm *vm, mrbc_value v[], int argc){
  SET_INT_RETURN( funSysTick64()/DELAY_US_TIME );
}

あとは、これをmethodとして定義すれば、rubyから使えるようになる。

mrbc_define_method(0, 0, "ticks_us", c_ticks_us);

しかし、この機能を組込んでコンパイルしたら、1k以上も大きくなってしまった。 今回は時間が必須なので仕方無いが、通常はこの機能は組込まないで良いだろう。

ch32x035を使って、

while true
  printf "%d\r\n",ticks_us
  sleep_ms 1
  printf "%d\r\n",ticks_us
  sleep 1
end

を実行したら、2.1msぐらいの時間が消費されていた。 10msだけsleepするようにしたら11.1msぐらいかかったので、 sleepの前後の処理と表示する部分で1msぐらいかかっているようだ。

二つの信号の変化があったときに、その時間とピンの状態を表示するために、 以下のようなプログラムを走らせてみた。

green=GPIO.new(25,GPIO::IN)
blue=GPIO.new(35,GPIO::IN)
pg=0
pb=0
while true
  g=green.read
  b=blue.read
  next if pg==g and pb==b
  printf("%d,%d,%d\r\n",ticks_us,pg=g,pb=b)
end

これを使って信号をモニタしたところ、 ある信号は約500マイクロ秒で変化したように表示されるので、表示自体はそれ以下の時間で行われているようだ。 表示時間を考慮するならば、信号を一旦は配列にためておいて、まとめて表示すると良いかも知れない。

Read more...

mruby/cのStringを無効化した状態でUART

mruby/cでStringを無効化することができるようになった。 私が最近いじっているch32funを用いたCH32X035用の環境では、Stringが無いとそのままではI2CやSPIは動かなかったが、 出力はmake_output_bufferでStringを使わないようにして、 入力は文字列を整数の配列に変換することにより、動くようになった。 しかし、入出力ともにStringであるUARTは動かせていなかった。 APIのガイドラインとは異なる仕様になるが、UARTの入出力もI2CやSPIと同様の処理をすれば、String無しでもUARTを使えるようになるはずである。 今回はそのやり方について考えてみたい。

I2CやSPIでは、マイコンはセンサーなどのICと通信し、やり取りされるデータは数値であることが多い。 一方UARTでは、通信相手はPCや別のマイコンで、文字列をやり取りすることも多い。 それゆえに、UARTの入出力でStringを使うようになっているのだろう。 Stringを無効にした場合には、当然Stringは使えないが、Symbolを使えば限定的ではあるが文字列を扱うことができる。 そこで、 make_output_bufferでSymbolも使えるようにして、それをUARTの出力用に使うと良いと考えた。 UARTで出力するときには、通常はStringが引数として与えられるが、make_output_bufferはStringも受け付けることができるので、UARTでも問題無く動作する。 Stringを無効にしたときも考慮して、数値や数値の配列に加えて、Symbolを使って、出力すべきデータを指定するのである。 入力では、それをSymbolに変換することは可能であるが、mruby/cのSymbolには、GCが働かないようなので、様々なデータを受け付けたてSymbolに変換すると、メモリが圧迫されてしまう。 I2CやSPIと同様に、入力されたデータは数値の配列にするしか無いだろう。

Stringを無効にした このような限定的な仕様にしたときに、UARTが何の程度の実用性があるかを、 例えば標準入出力とUARTのコンバーターが作れるかを考えてみよう。 標準入力は、getbyteで数値として受け取るので、それを数値としてUARTで出力すれば良い。 UARTからの入力は、数値の配列となるが、数値はprintfで%cを指定すれば、文字として標準出力に出すことができる。 つまり、Stringが無くても、コンバーターが作れることが分かる。

mruby/cの コンパイルサイズを小さくするには、使わないAPIを組み込まないという方法もあるが、様々な状況に対応して、ソースを書き換えるのは面倒である。 それに対して、FloatやStringを無効にするのは、vm_config.hの中の指定を変更するだけで良い。 CH32X035用の環境では、Floatをすでに無効にしていたが、 さらにStringを無効にすると約10kバイト小さくなり、 String以外のmrblibを組み込んでも、 flashに10k以上の余裕ができる。 それだけあれば、かなり複雑なrubyのプログラムも組み込むことができる。 Stringを使って手軽に小さなプログラムを使う場合と、Stringを使わずに比較的大きなプログラムを作る場合用に、二種類のbinaryを用意しておけば、本体をコンパイルする必要はなく、mrbcだけ作って、binaryと結合して書き込めば良いので、便利だと思う。

Read more...