ch32v203用のmrubyc_arduino
ch32v203には、公式なflashが64kと、さらに非公式で160kのflashが搭載されている。 mrubyc_arduinoに標準のAPIを組み込むと64kほどになるので、ch32v203はmrubyc_arduinoを使ってみるのに最低限の機能を有したマイコンの一つと言えるだろう。 ch32v203でmrubyc_arduinoを動かすための情報については、 これまでにこのブログにいろいろなことを書いて来たが、 その使い方をここにまとめておこうと思う。
まず、Arduinoでmrubycが使えるようにライブラリを追加する。 mrubyc_arduino をzipとしてdownloadして、「スケッチ-ライブラリをインクルード-.ZIP形式のライブラリをインストール」からインストールする。 そのライブラリに標準のAPIを追加するために、 以前紹介した私が作ったmrbc_*.*やoutputbuffer.cを ~/Arduino/libraries/mrubyc_arduino-main/src にコピーする。 また、これらを取り込むように、mrubyc.hに以下を追加する。
#include "mrbc_gpio.h" #include "mrbc_adc.h" #include "mrbc_pwm.h" #include "mrbc_i2c.h" #include "mrbc_spi.h" #include "mrbc_uart.h" #include "mrbc_get.h"
ここで、ファイル名はmrbc_*に統一したので、過去のブログとはファイル名が若干異なっている場合があるので注意して欲しい。 ch32やESP8266では、バイトオーダのオプションを変更する必要があり、 vm_config.hの中の以下の行を、コメントアウトを外して有効にする。
#define MRBC_REQUIRE_32BIT_ALIGNMENT
これで、mrubyc_arduinoの準備は完了である。
次に、Arduinoでch32を使えるようにパッケージを追加する。 設定のURLに以下を追加して、ボードマネージャーからch32を検索してWCHサポートをインストールする。
https://github.com/openwch/board_manager_files/raw/main/package_ch32v_index.json
WCHサボートのリリースにはToneなどが無いので、 最新版からTone.*とHardwareTimer.*を持って来て、~/.arduino15/packages/WCH/hardware/ch32v/1.0.4/cores/arduino/にコピーする。 これらのファイルを取り込むように、そのフォルダにあるwiring.hのHardwareTimer.hとTone.hのincludeをuncommentする。 Arduinoでは、ボードを撰択して、最適化のオプションはsmallest with LTOとしておく。
最後に、mrubyc_arudinoをch32v203用にカスタマイズする。 まず、そのままだと64kのflashに収まり切らないので、いくつかの機能を削って、工夫をする。 floatを消すために、vm_config.hのMRBC_USE_FLOATを0にして、2026/4/15のブログに書いたようにいくつかのファイルを修正する。 Taskも消すために、2026/4/20のブログに書いたようにrrt0.hとrrt0.cを修正して、_autogen_class_rrt0.hを削除する。 実行するタスクは一つだけになったので、vm_config.h中で指定されているMAX_VM_COUNTを1にする。 mrblibをメインのflashから消すために、mrblib.cを削除する。 これで、64kに収まるようになる。 Single Wire Debugを標準入出力にするために、2026/5/2のブログに書いたようにswd.hとswd.cを作って、Arduinoのスケッチと同じフォルダに置く。 Arduinoのスケッチは以下のようにした。
#include <mrubyc.h>
#include "swd.h"
#define MEMORY_SIZE (1024*10)
#define MRBLIB_CODE 0x8010000 //ch32v203
#define FLASH_CODE 0x8012000 //ch32v203
extern const uint8_t mrblib_bytecode[] = {
0x52,0x49,0x54,0x45,0x30,0x33,0x30,0x30,0x00,0x00,0x00,0x41,0x4d,0x41,0x54,0x5a,
0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x25,0x30,0x33,0x30,0x30,
0x00,0x00,0x00,0x19,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,
0x11,0x01,0x38,0x01,0x69,0x00,0x00,0x00,0x00,0x45,0x4e,0x44,0x00,0x00,0x00,0x00,
0x08,};
static uint8_t memory_pool[MEMORY_SIZE];
static volatile char inbytes=0;
static volatile uint8_t last=' ';
extern "C" {
void handle_debug_input( int numbytes, uint8_t * data ) {
inbytes+=numbytes;
last = data[0];
}
}
int hal_write(int fd, const void *buf, int nbytes) {
_write(0, (char*)buf, nbytes);
return (nbytes);
}
int hal_flush(int fd) { return 0; }
unsigned char hal_read(int fd) {
while(inbytes==0) _write(0, "", 1);
inbytes=0;
return last;
}
void setup() {
SetupDebugPrintf();
mrbc_init(memory_pool, MEMORY_SIZE);
mrbc_run_mrblib( MRBLIB_CODE );
mrbc_init_class_digital();
mrbc_init_class_adc();
mrbc_init_class_pwm();
mrbc_init_class_i2c();
mrbc_init_class_spi();
mrbc_init_class_uart();
mrbc_init_class_get();
mrbc_run_mrblib( FLASH_CODE );
}
void loop() {}
ここで、mrblib_bytecodeは、何もしないrubyスクリプトをmrbcで処理して得られたものである。 本当はmrblib_bytecodeにはアドレス0x8010000を代入したかったのだが、ポインタでは無いのでうまくいかず、本来mrblibを読み込むところでは、何もしないコードを読み込ませて、その後でアドレスを指定してmrbc_run_mrblibから本来のライブラリを組み込むようにした。 また、標準入力のバッファは面倒なので作っていない。 これをコンパイルすると、64kの98%になった。 そこで、WCH-LinkEで接続し、バイナリとして出力させたファイルをminichlinkでflashに書き込む。
./minichlink -w ch32v203.ino.bin flash -b
拡張flashにはmrblibを配置するのだが、 そのrubyのソース を取ってきて、以下のコマンドでbinaryファイルを作って書き込む。
mrbc --remove-lv -omrblib.bin enum.rb array.rb global.rb hash.rb numeric.rb object.rb range.rb string.rb ./minichlink -w mrblib.bin 0x8010000 -b
これで、基本的な設定は完了である。
ユーザーのプログラムは、mrblinの少し後の拡張flashにおく。 rubyスクリプトをtest.rbとして作ったら、以下のコマンドでコンパイルして書き込む。
mrbc test.rb mv test.mrb test.bin ./minichlink -w test.bin 0x8012000 -b
標準入出力を使うには、minichlinkをターミナルモードで実行する。
./minichlink -kT
この時、同時にマイコンをリセットしたければ、“k"を除いて実行すれば良い。
本当は、書き込みや標準入出力は汎用性の高いUSBを使うようにしたかったのだが、USB-CDCを組み込むと容量がかなり大きくなってしまうし、USBからflashの特定の場所に書き込むツールが見付からなかったので、SWDを書き込みと標準入出力に使うようにした。 標準のmruby/cと比較すると、FloatとTaskなどを削除してので、小数とマルチタスクは使えなくなったが、小さなマイコンで使う基本的な機能はrubyから使うようにすることができた。 今後、ch32v203に簡単な動作をさせるプログラムを作る際には使って行きたいと思う。 CH32V203を搭載した小型のマイコンボードとしては、BluePill+やWeActStudio WA00008やAdafruit QT Py CH32V203開発ボードやSuzuno32RV pro microなどがあるが、マイコン本体は秋月で120円ほどで売られているので、3.3Vのレギュレータと組合せれば、簡易のボードを自作することもできるだろう。 入手の容易さや価格などを考えると、最初の二つか自作が良いと思う。