mruby/cは複数のスクリプトを実行することができます。そのためMRBC_NO_TIMERを指定しない場合、時分割するために1msecのタイマー割り込みを使用します。
通常のスクリプトを一本実行しているときは、割り込みと通常処理が動いています。通常処理ではmrubyタスクを実行しています。
割り込み処理ではmrbc_tick()を呼んでmruby/cの処理をします。
mruby/cにはデフォルトで組み込みmethodのsleepとsleep_msがあります。
sleepすると処理対象のmrubyタスクがなくなるので通常処理でhal_idle_cpu()を呼んで次の割り込みまで省電力モードに入ります。RXマイコンの場合waitというインストラクションを使います。
sleepが終了するとwaitは呼ばれなくなります。
テストスクリプトを書いてみました。
#
# built in method sleep test
#
def print(val)
val.to_s.each_char do |n|
serial_write(n.ord)
end
end
begin
serial_init
loop do
serial_write(0x2a)
sleep 1
end
rescue StandardError => e
print e
end
動かしたところRX210でもRX631でも止まってしまいます。
RXマイコンのwaitは特権命令でユーザーモードで実行すると例外が発生していました。このためユーザーモードに入らないようにすることがitocさんの資料にあり、それで解決しました。
組み込み用途では常に特権(スパーバイザー)モードが一般的のようです。
mruby/cの複数の処理を動かせる仕組みはリアルタイムOSを意識したものなのかもしれません。
RX210はこれで動いたのですが、RX631はUSBの処理が動かなくなったので、hal.hの割り込み制御を外しました。正しい修正かどうかはわかりません。ユーザーモードと特権モードでは割り込みの制御が違うのかもしれません。