mruby/cのFloatについての小さなバグ
Arduinoを利用してESP32でmruby/cからGPIOとADCを使うことができるようにはなった。 私がよく使うマイコンは、ESP32よりもflashやメモリの小さなものなので、そのようなマイコンでmruby/cを動かせないかと思っている。 Arduino ZeroやXiao SAMD21に使われているATSAMD21G18Aとか、 WCHマイコンの中では高性能なch32v305などが、次のターゲットであろう。 これらは、今のやり方で動きそうに思うが、残念ながらこれらは手元には無いので、確かめられない。 さらにその次には、 ch32v203とか、 Arduino Nano Everyで使われているatmega4809などかな。 これらは、メモリも少ないが、flashも足りていない。 そこで、Arduino Nano Everyを例にして、mrubyc_arduinoのflashの削減ができないかを検討していたら、mruby/cの小さなバグを見付けたので、そのことについて書くことにする。
Arduino Nano Everyのflashは、48kである。 ADCを使った簡単なプログラムをmrubyc_arduinoでコンパイルすると、82k程となる。 flashの使用量をかなり減らさないといけない。 vm_config.hを見ると、以下のような指定がされている。
MRBC_USE_FLOAT 1 MRBC_USE_MATH 0 MRBC_USE_STRING 1
機能を制限して、flashやメモリの使用量を減らすオプションのようだ。 Floatをoffにするために、0にしてみたが、コンパイルでエラーが出てしまう。 試行錯誤の末、以下のような修正をすると、これを0にしても動くようにできた。 boxing_no.h, value.cの中には、".d"や"->d"などが使われているが、これらはfloatを使わない場合には使えなくなっているので、それらの使われている場所を以下で囲って無効にする。
#if MRBC_USE_FLOAT #endif
そして、_autogen_builtin_class.hの中の以下の行も、同様に囲む。
extern struct RBuiltinClass mrbc_class_Float;
最後に、class.cの中のclassの定義を以下のようにする。
#if MRBC_USE_FLOAT MRBC_CLASS(Float), // MRBC_TT_FLOAT = 5, #else 0, #endif
これで、floatをoffにしてもコンパイルが通るようになる。 Arduino Nano Everyの場合には、flashの使用量が5.5kぐらい減った。 同じくらい効果のある削減を、あと5個ぐらい組合せれば、動くようになるかも知れない。 mruby/cでFloatをoffにすることはあまり無いのかも知れないが、0にしたときにエラーが出るのは、一応のバグと言えるのでは無いだろうか。 Stringをoffにしようとしても、エラーが出るが、こちらはややこしそうなので、あまり手を付けていない。
さらにflashを減らす試みとして、あまり使わないclassを取り除けないかも試してみた。 具体的には、Range,Proc,Hash,Arrayなどがあまり使わないclassかなと思う。 十分には検証していないが、rangeではflashは1.5kしか小さくならなかった。 Proc,Hash,Arrayは、取り除いてみたが、vmのcoreの部分で使っている感じなので、うまく動かない可能性が高いと思う。 たとえ、これらを全て取り除いても、10kぐらいしか減らないことが分った。 今後、Rangeは殆ど消して、Proc,Hash,Arrayでは不要なmethodを取り除いたときに、どうなるかを確かめてみたいと思う。 また、rrt0.cの中には、複数のタスクを動かすためのプログラムが書かれているが、一つのタスクが動けば良いと考えれば、工夫するとflashの節約が出来る可能性もあるのでは無いだろうか。
2026/4/16追記 value.hにもマクロで".d"を使っている部分があったので、これも修正した。