拡張flashを活用するCH32V203用のmrubyc_arduino
CH32V203でmrubyc_arduinoを使うために、2026/5/3のブログでは、FloatとTaskを無効にしたり、mrblibを拡張flashに移動させたりする方法を紹介した。 拡張flashをさらに有効に活用することによって、Floatを無効にするだけで、mruby/cを動かすことに成功したので、その手法を紹介する。
環境の構築は、先のブログの通りである。 Arduinoのスケッチは非常に単純で、以下の通りである。
#include <mrubyc.h>
#include "swd.h"
#define MEMORY_SIZE (1024*10)
#define FLASH_CODE 0x8020000 //ch32v203
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_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_create_task( FLASH_CODE, 0 );
mrbc_run();
}
void loop() {}
これをそのままsmallest with LTOでコンパイルすると、flashの容量オーバーとなる。 そこで、constの配列などのデータを拡張flashに配置させるように指定する。 そのために、 ~/.arduino15/packages/WCH/hardware/ch32v/1.0.4/system/CH32V20x/SRC/Ld/Link.ldの容量の指定に拡張flashに対応するFLASH2を追加する。
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K FLASH2 (rx) : ORIGIN = 0x08010000, LENGTH = 160K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
そして、同じファイルに.data2を作って、.textからrodataを含む二行を移動して、これがFLASH2に入るように指定する。
.data2 :
{
. = ALIGN(8);
*(.rodata)
*(.rodata*)
. = ALIGN(8);
} >FLASH2 AT>FLASH2
これで、constなどが通常のflash上の.textから、拡張flash上の.data2に移動する。 当然、mrblibも移動することになる。 この状態でsmallest with LTOでコンパイルすると、flashの九割ほどになる。 難しいのはここから、binaryを取り出す作業である。 そのままバイナリを出力すると、130Mほどになるので、無駄が多い。 Linuxでは、コンパイルを実行すると、/tmp/arduino_build_*にelfファイルが出来ているので、これをtemp.elfとして、~/.arduino15/packages/WCH/tools/riscv-none-embed-gcc/8.2.0/binにコピーする。 そして、以下のコマンドを実行すると、通常のflashと拡張flashに書き込む二つのファイルができる。
./riscv-none-embed-objcopy -O binary -R .data2 temp.elf temp1.bin ./riscv-none-embed-objcopy -O binary -j .data2 temp.elf temp2.bin
これらを以下のコマンドで書き込めば終了である。
./minichlink -w temp1.bin flash -b ./minichlink -w temp2.bin 0x8010000 -b
ユーザー用のmrbは0x8020000に書き込む。 platform.txtのcompiler.elf2bin.extra_flagsに-R .data2と指定して、通常のflashの内容だけがバイナリに出力されるようにして、拡張flashの内容は別途取り出すようにした方が良いかも知れない。
Floatを無効にした以外は、mruby/cの機能をほぼ使えるようなCH32V203用の環境が構築できた。 Taskが使える以外は以前とあまり変わらないが、mruby/cのコードをほとんど加工すること無く組み込めたという意味で、こちらの方が良い気がする。 しかし、拡張flashにはmrblib以外にも定数などが載ったので、実行速度は少し遅くなっているかも知れない。 また、すべての機能が動くことを確認したわけでは無いので、何か不都合がある可能性もあり、今後に検証する必要があるだろう。