ch32funのmruby/cでTaskの削除
最近、安価なCH32X035をmruby/cから使うための環境の開発を行っているが、 このマイコンにはflashが62kしか無いので、ある程度機能を制限する必要がある。 まず、Floatの削除は必須である。 mrbとして組み込んでいたmrblibも、組み込まないようにすることで、使えるmethodが減ってしまうが、容量を減らすことができる。 この状態で、flashは1k程余るのだが、ユーザーのプログラムが少し長くなると、足り無くなるだろう。
このような単純なマイコンでマルチタスクをすることは無いので、Taskも削ることができる。 mrubyc_arduinoについて2026/4/20に書いたようにして、 さらにTaskを削除すると、約3k小さくなり、合計で約4kのflashがあれば、通常の使用には十分であろう。 以前のTaskの削除の仕方は、rrt0.hやrrt0.cの中身を書き換えないといけなかったが、もう少し単純な方法を発見したので、それを紹介しよう。
まず、rrt0.hとrrt0.cと_autogen_class_rrt0.hは、完全に消してしまってよい。 ただし、mrubyc.hでrrt0.hをincludeしているので、その行をコメントアウトする。 そして、メインのコードで、rrt0.cの中でされていたメモリ確保やsleepなどの定義をすれば、Taskを削除できる。 メインのコードが少し長くなるが、この方が単純だろう。 その際のmain.cは、以下のようになる。
#include "ch32fun.h"
#include <stdio.h>
#include "fsusb.h"
#include "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"
#define MEMORY_SIZE (1024*10)
static uint8_t memory_pool[MEMORY_SIZE];
#define FLASH_CODE (0x8000000+59152)
#define RX_BUFFER_SIZE 64
volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
volatile uint8_t rx_head = 0;
volatile uint8_t rx_tail = 0;
void rx_buffer_push(uint8_t c) {
uint8_t next = (rx_head + 1) & (RX_BUFFER_SIZE - 1);
if (next != rx_tail) {
rx_buffer[rx_head] = c;
rx_head = next;
}
}
bool rx_buffer_available(void) {
return rx_head != rx_tail;
}
uint8_t rx_buffer_pop(void) {
if (rx_head == rx_tail) return 0;
uint8_t c = rx_buffer[rx_tail];
rx_tail = (rx_tail + 1) & (RX_BUFFER_SIZE - 1);
return c;
}
void handle_usbfs_input(int numbytes, uint8_t *data) {
for( int i = 0; i < numbytes; i++ ) rx_buffer_push(data[i]);
}
unsigned char hal_read(int fd) {
while(!rx_buffer_available());
return rx_buffer_pop();
}
long atol(const char *str) {
return (long) mrbc_atoi( str,10 );
}
static void c_sleep(mrbc_vm *vm, mrbc_value v[], int argc){
if(argc>0){
mrbc_int_t sec = mrbc_integer(v[1]);
SET_INT_RETURN(sec);
Delay_Ms(sec * 1000);
}
}
static void c_sleep_ms(mrbc_vm *vm, mrbc_value v[], int argc){
if(argc>0){
mrbc_int_t sec = mrbc_integer(v[1]);
SET_INT_RETURN(sec);
Delay_Ms( sec );
}
}
int main()
{
SystemInit();
funGpioInitAll();
funAnalogInit();
hal_init();
mrbc_init_alloc(memory_pool, MEMORY_SIZE);
mrbc_init_global();
mrbc_init_class();
mrbc_define_method(0, 0, "sleep", c_sleep);
mrbc_define_method(0, 0, "sleep_ms", c_sleep_ms);
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();
USBFSSetup();
mrbc_run_mrblib( (uint8_t *) FLASH_CODE );
while(1){}
}
atolとほとんど同じことをする関数をmruby/cのコードの中に発見したので、それを使うことによって、さらに少しだけコンパクトになっている。 コンパイルした時のサイズがFLASH_CODEの所の値と異なっている場合には、それを変更して、コンパイルし直す。 私の環境では、58k程度となって、flashに約4.2kの余裕があることが確かめられる。
mrubyc_arduinoで環境の構築を行っていたときには、それでも容量オーバーになるので、C言語で書かれているmethodの数を減らしたりと、さらなる機能の制限が必要であった。 しかし、ch32funを使ったことによって、かなり容量が減ったので、上記の三つの工夫で余裕を持ってflashに収まるようになった。