UIAPduino環境のコンパイルサイズの謎
私がUIAPduino用に新しく作っているArduino環境で,なぜかblink.inoのコンパイルサイズが大きくなってしまう. UIAPduinoの公式よりは三割程度は小さいのだが,明らかに大きすぎる気がする. 試行錯誤しながら,その理由を考えていたのだが,ヒントが見つかった気がするので,そのことについて説明する.
私の環境でのBlink.inoのコンパイルサイズは,AlexanderManderaさんの環境よりも2.3kバイトほど大きい. まずは冗長な処理を行っていたピンの定義などを簡略化して40バイトぐらいは小さくなったが,2kバイトには程遠い. 他の部分もいじってみたが,それほど無駄なことをしていないように見える.
ch32funの部分に無駄が無いかを調べていて,FUNCONF_TINYVECTORというパラメータを見つけた. AlexanderManderaさんの環境でも,-DTINYVECTORという指定をしていて,なんだろうと思っていたが,これに対応するようだ. このオプションを有効にしたら,私の環境でもコンパイルサイズが2kバイト以上小さくなった. 一番大きな要因はここにあったようだ. しかし,このオプションを有効にすると,割り込みが使えなくなる. 例えば,PWMなども働かなくなってしまったし,USBも使えなくなった. それでは意味が無いので,TINYVECTORは使わないことにした.
ch32v003には,40個ほどの割り込みがあり,そのベクターテーブルは,合計でも160バイト程度のはずである. TINYVECTORはそのほとんどを無くしてしまうというオプションなのだが,普通に考えると160バイト程度しか,コンパイルサイズに影響しないはずである. しかし,Arduinoでコンパイルすると,2kバイト以上の違いになる. 割り込み一つあたり50バイト程度が,何かに使われていると予想される. 少なくとも割り込み時に実行される40個ぐらいの関数を定義するのに,それぞれ多少のバイト数は必要になるだろう. Wireのコードをいじっていたときに,一つの処理を関数に置き換えるとあまりバイト数が変わらないけど,同一の二つの処理を関数に置き換えると数十バイト大きくなるということがあった. 一つの処理の場合には,最適化によって,関数としては使われず,二回使ったときに,関数として使われるとすると,一つの割り込み関数で50バイト増えるのも無難な気がする. ch32funの中では,ユーザーが定義していない割り込みは,DefaultIRQHandlerのaliasになっているので,実質一つの関数なのだが,Arduinoでは何らかの理由でalias指定が働かないとすると,2kバイト大きくなることが説明できる. これが正しいとすると,このalias指定を有効にして,その時に使用する割り込みのみを関数として使うようにすれば,2kバイト弱はサイズが小さくできる可能性があるのでは無いだろうか.
ch32funを使っているという共通点のあるAlexanderManderaさんの環境と,コンパイルサイズが違う原因が分かってすっきりした. 機能の面も合わせて考えると,ようやく私の環境がこの環境に劣っている点は,ほぼ無くなったと言える. USBを使えるという大きな利点があるものの,WireのslaveやSPIにはまだ対応できていない. 私はあまり使わないので忘れていたけど,ピン割り込みも対応するかな. 今後は,Arduino環境でのalias指定という観点に着目して,コンパイルサイズを小さくできる可能性について,もう少し調べてみたい.