ch32funのmruby/cでCH32X035用にインストール
CH32X035をmruby/cから使うためのch32funを利用したプログラムは、ほぼ完成に近付いたと思っている。 その情報は主に今月のブログに書かれているが、ファイルの数も増えて来たし、複雑になっているように感じる。 私でも、このブログの内容を元に、それを再現するのは時間がかかりそうだ。 そこで、この環境を簡単に構築するシェルスクリプトを書いてみた。
まず、事前にrubyをインストールしておく必要がある。 また、wgetとsedやawkも使っているので、これらも同様であるが、通常のlinuxではすでに使える様になっているはずである。 適当なフォルダを作って、以下のスクリプトを実行すると、必要なファイルを取って来て、適切に修正するようになっている。
# download
wget https://github.com/mrubyc/mrubyc/archive/refs/tags/release3.4.1.zip
wget https://github.com/cnlohr/ch32fun/archive/refs/heads/master.zip
wget https://github.com/ch32-rs/wchisp/releases/download/nightly/wchisp-linux-x64.tar.gz
# unzip and copy
mkdir mrubyc_ch32fun
unzip master.zip
mv ch32fun-master/ch32fun/ mrubyc_ch32fun/
mv ch32fun-master/extralibs/ mrubyc_ch32fun/
mkdir mrubyc_ch32fun/mrubyc
unzip release3.4.1.zip
mv mrubyc-release3.4.1/src/ mrubyc_ch32fun/mrubyc/
mv mrubyc-release3.4.1/support/ mrubyc_ch32fun/mrubyc/
mv mrubyc-release3.4.1/mrblib/ mrubyc_ch32fun/mrubyc/
cat mrubyc-release3.4.1/hal/minimal.h | awk '/define MRBC_SRC/{$0=$0"\n#include \"ch32fun.h\""}1' |sed 's/delay/Delay_Ms/' > mrubyc_ch32fun/mrubyc/src/hal.h
tar xzvf wchisp-linux-x64.tar.gz
# usb
awk '/void HandleDataOut/{a=1}a&&/^}/{$0="\tpoll_input();\n"$0;a=0}/USBPRINTF/&&!u{$0="0 //"$0;u=1}1' mrubyc_ch32fun/extralibs/fsusb.c >temp.tmp && mv temp.tmp mrubyc_ch32fun/extralibs/fsusb.c
# modify files
cd mrubyc_ch32fun/mrubyc/src
make autogen # require ruby
# remove task
rm rrt0.c rrt0.h _autogen_class_rrt0.h
sed -i -e 's@#include "rrt0@//#include "rrt0@' mrubyc.h
# setting
sed -i -e 's/MRBC_USE_FLOAT 2/MRBC_USE_FLOAT 0/' -e 's@// #define MRBC_REQUIRE_32BIT_ALIGNMENT@#define MRBC_REQUIRE_32BIT_ALIGNMENT@' vm_config.h
# remove mrblib
sed -i -e 's@ extern@ //extern@' -e 's@ mrbc_run_mrblib@ //mrbc_run_mrblib@' class.c
rm mrblib.c
# for float
awk '/->d/{$0="#if MRBC_USE_FLOAT\n"$0"\n#endif"}1' boxing_no.h >temp.tmp && mv temp.tmp boxing_no.h
awk -v RS="" '/MRBC_TT_FLOAT/ && !/MRBC_USE_FLOAT/{$0="#if MRBC_USE_FLOAT\n"$0"\n#endif"}/return val->d;\n\}/{$0="#if MRBC_USE_FLOAT\n return val->d;\n#else\n return 0;\n#endif\n}"}{$0=$0"\n"}1' value.c >temp.tmp && mv temp.tmp value.c
awk '/mrbc_class_Float/{$0="#if MRBC_USE_FLOAT\n"$0"\n#endif"}1' _autogen_builtin_class.h >temp.tmp && mv temp.tmp _autogen_builtin_class.h
awk '/MRBC_CLASS\(Float/{$0="#if MRBC_USE_FLOAT\n"$0"\n#else\n 0,\n#endif"}1' class.c >temp.tmp && mv temp.tmp class.c
awk '/define MRBC_TO_INT/{$0="#if MRBC_USE_FLOAT\n"$0;a=NR}a&&NR==a+3{$0="#else\n#define MRBC_TO_INT(val) (val).i\n#endif\n"$0}1' value.h >temp.tmp && mv temp.tmp value.h
# mrbc_*
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260619/ | ruby -e "d=ARGF.read.split(/<.?pre>/);open('mrbc_gpio.h','w'){|f|f.print d[1].gsub(/</,'<')};open('mrbc_gpio.c','w'){|f|f.print d[3].gsub(/</,'<')};"
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260413/ | ruby -e "d=ARGF.read.split(/<.?pre>/);open('mrbc_adc.h','w'){|f|f.print d[5].sub(/<Arduino.h>/,'\"ch32fun.h\"')};open('mrbc_adc.c','w'){|f|f.print d[7].sub(/adc.+?digital.h/m,'mrbc_adc.h').sub(/.+pinMode.+\s+/,'').gsub(/analog/,'funAnalog')};"
awk '/GET_INT_ARG/{$0=" if(argc>0){\n uint8_t dpin = GET_INT_ARG(1);\n handle->pin_num = ((dpin>>1)==12)? dpin-16 : ((dpin>>2)==12)? dpin-38 : ((dpin>>3)==0)? dpin : 15;\n }"}1' mrbc_adc.c >temp.tmp && mv temp.tmp mrbc_adc.c
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260605/ | ruby -e "d=ARGF.read.split(/<.?pre>/);open('mrbc_pwm.h','w'){|f|f.print d[1]};open('mrbc_pwm.c','w'){|f|f.print d[3].gsub(/</,'<')};"
sed -i -e '2a #include "mrbc_gpio.h"' -e '6a 0, 0, 0, 0, 0, 0205, 0206, 0207,' -e '8a 0241, 0242, 0243, 0244, 0, 0211, 0, 0,' -e '10a 0114, 0, 0322, 0321, 0, 0, 0, 0,' -e 's/pin>=48/pin>=72/' -e 's/funPinMode/funPinMode2/' mrbc_pwm.c
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260608/ | ruby -e "d=ARGF.read.split(/<.?pre>/);open('mrbc_i2c.h','w'){|f|f.print d[1]};open('mrbc_i2c.c','w'){|f|f.print d[3].gsub(/</,'<')};"
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260610/ | ruby -e "d=ARGF.read.split(/<.?pre>/);open('mrbc_spi.h','w'){|f|f.print d[1]};open('mrbc_spi.c','w'){|f|f.print d[3].gsub(/</,'<')};"
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260612/ | ruby -e "d=ARGF.read.split(/<.?pre>/);open('mrbc_uart.h','w'){|f|f.print d[1]};open('mrbc_uart.c','w'){|f|f.print d[3].gsub(/</,'<')};"
# hal.c
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260615/ | ruby -e "d=ARGF.read.split(/<.?pre>/);open('hal.c','w'){|f|f.print d[1]};open('mrbc_get.h','w'){|f|f.print d[3]};open('mrbc_get.c','w'){|f|f.print d[5].gsub(/</,'<')}"
# make_output_buffer
wget -O - https://github.com/HirohitoHigashi/mrubyc-nucleo-F401RE/raw/refs/heads/chapter05_i2c/Core/mrubyc/stm32f4_i2c.c | ruby -e "print '#include \"mrubyc.h\"'+ARGF.read.split(/===+/)[1]" > outputbuffer.c
# user program
cd ../../..
mkdir mrubyc_ch32fun/ch32x035
cp wchisp-linux-x64/wchisp mrubyc_ch32fun/ch32x035/
cp ch32fun-master/examples_usb/USBFS/usbfs_cdc_tty/usb_config.h mrubyc_ch32fun/ch32x035
cd mrubyc_ch32fun/ch32x035
chmod +x wchisp
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260603/ | awk -v RS='##' -F '</?pre>' '{print $2}' > funconfig.h
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260601/ | awk -v RS='##' -F '</?pre>' '{print $2}' > Makefile
wget -O - https://www.ipc.shimane-u.ac.jp/weda/SetupDiary/2026/20260617/ | awk -v RS='##' -F '</?pre>' '{print $2}' | sed 's/</</g' > main.c
ここで、wchispはamd64用を指定しているので、必要に応じて変更する。 mrblibも使う可能性があるので、そのフォルダも移動している。 ファイルの細かな修正をするのに、最初はsedやawkで頑張っていたが、面倒になってrubyを使ってしまった。 GPIOのpinの数値を16毎から24毎に変更したことに伴って、PWMに変更が必要になったが、その修正も加えてみた。 ついでに、ADCの番号をch32funのpinの数値から指定できるように変更した。 つまり、この環境においては、ピンなどの指定はすべて、PAはそのままの数字、PBは24を足した数字、PCは48を足して行う。 以前は ADCだけはADCの番号を指定しないといけなかったが、それも上記の番号に統一した。 ADCの番号の変更で50バイトほど大きくなってしまったが、使い勝手を良くするためなので、仕方無いだろう。 ちなみに、ADCを使えない数値を指定したら、参照電圧に対応させるようにした。 fsusb.cにpoll_inputを加えるついでに、ANYPRINTFも無効になるようにした。 これによってch32funのprintfを使わなくなったはずで、350バイトぐらい小さくなった。
これで、インストールは非常に簡単になったので、あとはコンパイルである。 ch32funのコンパイルに必要なソフトは、以下のコマンドでインストールできる。
sudo apt-get install build-essential libnewlib-dev gcc-riscv64-unknown-elf libusb-1.0-0-dev libudev-dev
そして、mrubyc_ch32fun/ch32x035に移動して、make buildとすると、main.binができる。 このとき、そのファイルサイズがmain.cのFLASH_CODEのところの数字と違っているだろうから、それを書き換えてもう一度コンパイルする。
これで、ch32funを使ったCH32X035用のmruby/cのbinaryを簡単に作ることがができるようになった。 マイコンを制御するプログラムをrubyで書く際には、 FloatとTaskとmrblibが使えないことを意識しなければならない。 それをmrbcで処理して、catを使ってmain.binと結合して、wchispで書き込めば、準備完了である。