ch32v203でmrubyc-arduinoを動かす


ch32v203は64kのflashを持つので、多少の工夫をすれば、mrubyc-arduinoを使えそうだと思い、試してみた。 なかなか動かなくて苦労したが、最終的には隠しflashにmrbcのコードを書き込むことによって、便利に使えることが分かった。

mrubyc-arduinoにdigital,adc,pwmを組込むと、flashには収まりきらないが、以前のブログに書いたようにfloatをoffにすると、ぎりぎり入るようになる。 このとき、最適化はsmallest+LTOが良い。 これでch32v203に書き込んだら、うまく動いてくれないかなと思ったが、動かない。 シリアルにも繋げていない状態だったので、ピンの電圧でしか状態をモニタできなかったので、原因を見付けるのに苦労した。 mrbc_init中で呼ばれているmrbc_init_classで止まっているところまで分かって、 さらに mrbc_run_mrblib、mrbc_load_mrb、mrbc_load_irep、load_irep、load_irep_1と辿って、念の為にbin_to_uint16を見ていたら、ようやく原因が明らかになった。 ch32v20xは、32bit-alignmentになっているようで、 vm_config.hでコメントアウトを外して、以下のように定義しておかないといけないことが判明した。

#define MRBC_REQUIRE_32BIT_ALIGNMENT

ESP8266でもなかなか動かせなくて困っていたが、同じ原因のようだ。

ようやく動くようになったので、いろいろと試していたが、ch32v203には、64kのflashの後に、アクセスの遅い160kのflashがあり、mrbのコードはここに配置すると良いということに気が付いた。 そこで、拡張flashに置いたmrbのコードを走らせるArduinoのスケッチを以下のように書いてみた。

#include <mrubyc.h>

#define MEMORY_SIZE (1024*10)
static uint8_t memory_pool[MEMORY_SIZE];

int hal_write(int fd, const void *buf, int nbytes) {
  return (nbytes);
}
int hal_flush(int fd) { return 0; }

void setup() {
  mrbc_init(memory_pool, MEMORY_SIZE);
  mrbc_init_class_digital();
  mrbc_init_class_adc();
  mrbc_init_class_pwm();
  mrbc_create_task( 0x8010000, 0 );
  mrbc_run();
}

void loop() {}

ch32v203とWCH-LinkEと接続して、バイナリとして出力したbinを以下のコマンドで書き込む。

./minichlink -w sketch.bin flash -b

mrbのコードは、以下ように作成して、拡張flashに書き込む。

mrbc test.rb
mv test.mrb test.bin
./minichlink -w test.bin 0x8010000 -b

すると、拡張flashに配置したコードでも無事に動いた。 これまでは、mrbのコードをarduinoに組み込んでいたので、rubyスクリプトを書き換えると、その度にarduinoでコンパイルしなければならなかったが、この手法だとmrbcでコンパイルして拡張flashに書き込むだけである。 これが本来のmruby/cの使い方と言えるだろう。

今回、ch32v203でmruby/cを動かすにあたって、試行錯誤の結果、mruby/cの中身の理解が若干は深まった。 例えば、mrbのコードはmrbc_run_mrblibで実行することが可能であることが分かった。 シングルタスクのみで良いのであれば、rrt0中のほどんどは不要で、sleepとinit部分だけを残して、mrbはmrbc_run_mrblibから動かすことにすれば、flashの占有サイズを小さくできるだろう。 また、初期化の部分で組込まれるmrblib.c中のmrbコードも4.5kぐらいあるので、それも拡張flashに移動させることも可能であろう。 mrbc用に確保するメモリの量は、最低限でどの程度必要なのか分からないが、4kでは動かないことはEPS32で確認している。 もしかすると、mrblib.c中の4.5kを一度に組み込むために、多くのメモリが必要なのかも知れない。 これを少しずつ組み込むようにしたら、必要なメモリが減らないかな。

flashが64k+alphaでRAMが20kのch32v203では、floatをoffにすることで、mrubyc-arduinoを使えることを示すことができた。 mrbのみを書き換えることで、rubyスクリプトからマイコンを制御できる。 このマイコンはUSBの機能を内蔵しているので、USBから拡張flashに書き込めれば、書き込み機も不要になるはずだが、これが出来るかは今後調べてみたい。 ついでにesp8266でもやっと動かせるようになったので、wifiなどを使ってみたいな。 最新のmruby/cを、さらに小さなflashやメモリで動かせるかは、引き続き考えてみたい。