一往確認日記 |
2023年03月27日 [長年日記]
_ irBoardの近況について
irBoardが起動できない問題があり、ご迷惑をおかけしております。
iOS 15以降、恐らくA12以降のCPUを用いたiOSデバイスで起動できないと思います。(旧iOS機種、旧OSではまだまだ動いております。)
3rdパーティの開発環境を使っていたこともあって原因の特定が難しくなかなか解決できずに申し訳ありません。
3rdパーティの開発環境での原因特定は諦めて、Apple純正の最新の開発環境で一から作り直しをしています。
現象の発覚から1年経ってしまいますが、Keyence製PLCでようやく動きつつあります。
もう少しまとまってきたらβテスト版で試していただける様にしたいと考えております。
その際はご協力いただけたら幸いです。
2022年04月04日 [長年日記]
_ irBoard 有料版一時停止のお知らせ
A14 または A15 Bionicチップを使用した iPhoneまたはiPadとiOS15の組み合わせでirBoardが起動できないまたは異常終了を頻発する現象が報告されています。
現在調査中ですが、今の所解決の目処立っておりません。
大変申し訳ありませんが、有料版の irBoard と irBoard Player を一時的に配信停止させていただきます。
組み合わせによっては問題なく動作する場合もありますので、irBoard Enterprise、irBoard Player for Deviceは継続して提供いたします。
irBoard Lite で問題なく動作しその組み合わせで運用を計画されている場合は 、irBoard Enterprise、irBoard Player for Device の利用をご相談ください。
問題が解決しましたら改めて提供させていただきます。
ご不便をおかけしますがご了承ください。
2021年03月18日 [長年日記]
_ PLCでmruby (8) irep_header
前回からだいぶ空いてしまいました。
前回はrite_section_irep_headerについて調べました。
今回はその中身になります。
手がかりは前回出てきたdump.cファイルのsection_irep_sizeを計算している箇所です。
section_irep_size = sizeof(struct rite_section_irep_header);
section_irep_size += get_irep_record_size(mrb, irep);
rite_section_irep_headerに加算しているget_irep_record_size()関数を見てみます。
static size_t
get_irep_record_size(mrb_state *mrb, const mrb_irep *irep)
{
size_t size = 0;
int irep_no;
size = get_irep_record_size_1(mrb, irep);
for (irep_no = 0; irep_no < irep->rlen; irep_no++) {
size += get_irep_record_size(mrb, irep->reps[irep_no]);
}
return size;
}
get_irep_record_size()では更にget_irep_record_size_1()を呼び出しています。
static size_t
get_irep_record_size_1(mrb_state *mrb, const mrb_irep *irep)
{
size_t size = 0;
size += get_irep_header_size(mrb);
size += get_iseq_block_size(mrb, irep);
size += get_catch_table_block_size(mrb, irep);
size += get_pool_block_size(mrb, irep);
size += get_syms_block_size(mrb, irep);
return size;
}
ここからrite_section_irep_headerにつづいてirep_header、iseq_block、catch_table_block、pool_block、syms_blockと続くと思われます。
まず、irep_headerを確認します。 write_irep_header()がそれに該当しそうです。
static ptrdiff_t
write_irep_header(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf)
{
uint8_t *cur = buf;
cur += uint32_to_bin((uint32_t)get_irep_record_size_1(mrb, irep), cur); /* record size */
cur += uint16_to_bin((uint16_t)irep->nlocals, cur); /* number of local variable */
cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */
cur += uint16_to_bin((uint16_t)irep->rlen, cur); /* number of child irep */
return cur - buf;
}
recode size, number of local variable, number of register variable, number of child irep の順で並んでいる様です。
Ruby scriptで確認してみます。
codes = File.read "a.mrb"
size_of_rite_binary_header = 22
size_of_rite_section_irep_header = 12
section_top = size_of_rite_binary_header + size_of_rite_section_irep_header
recode_size = codes[section_top + 0, 4].unpack("N").first
number_of_local = codes[section_top + 4, 2].unpack("n").first
number_of_register = codes[section_top + 6, 2].unpack("n").first
number_of_child_irep = codes[section_top + 8, 2].unpack("n").first
pp recode_size: recode_size, number_of_local: number_of_local, number_of_register: number_of_register, number_of_child_irep: number_of_child_irep
出力はこちらです。
{:recode_size=>26,
:number_of_local=>2,
:number_of_register=>3,
:number_of_child_irep=>0}
サイズは26バイトで、ローカル変数は2個、レジスターは3個、子はなしとなっています。
つづく
[book] 論語と算盤
大河ドラマ「青天を衝け」を観ています。
NHK+に登録したので1週間以内なら都合の良いときに見れるので便利です。
ドラマで渋沢栄一氏に興味を持ちましたので、氏の著書である「論語と算盤」を読み始めました。
2021年01月15日 [長年日記]
_ PLCでmruby (7) irep_header
前回rite_binary_headerについて調べました。
その次は何になるのか?ということです。
手がかりはdump.cのdump_irep関数です。
この中でバイナリーのサイズを計算しているところがあるのですが、rite_binary_headerの次はどうやらirepセクション、linenoセクション、lvセクション、rite_binary_footerと続くようです。
*bin_size = sizeof(struct rite_binary_header) +
section_irep_size + section_lineno_size + section_lv_size +
sizeof(struct rite_binary_footer);
irepセクションの手がかりはsection_irep_sizeを計算しているところで、
section_irep_size = sizeof(struct rite_section_irep_header);
section_irep_size += get_irep_record_size(mrb, irep);
まずはrite_section_irep_headerがあることがわかりました。
恐らくrite_section_irep_headerは子ノードがあるので再起的にサイズを計算しているのがget_irep_record_sizeではないかと思います。
それではrite_section_irep_headerについて調べます。
dump.hに定義があります。
struct rite_section_irep_header {
RITE_SECTION_HEADER;
uint8_t rite_version[4]; /* Rite Instruction Specification Version */
};
RITE_SECTION_HEADERはマクロになっているので、展開するとこの様になります。
struct rite_section_irep_header {
uint8_t section_ident[4];
uint8_t section_size[4];
uint8_t rite_version[4]; /* Rite Instruction Specification Version */
};
Rubyで確認するコードを書きます。
# read binary codes
codes = File.read "a.mrb"
# read rite_section_irep_header
size_of_rite_binary_header = 22
section_top = size_of_rite_binary_header
section_ident = codes[section_top + 0, 4]
section_size = codes[section_top + 4, 4].unpack("N").first
rite_version = codes[section_top + 8, 4]
pp section_ident: section_ident, section_size: section_size, rite_version: rite_version
結果はこのようになります。
{:section_ident=>"IREP",
:section_size=>38,
:rite_version=>"0300"}
IREPというIDがあり、サイズは38でバージョンは300となっています。
300は多分mruby 3.0を示していると思われます。
mrubyのバージョンは多分ここを調べれば良いことが分かりました。
2021年01月05日 [長年日記]
_ あけましておめでとうございます。
大雪で明けた2021、毎日の雪寄せに明け暮れています。
年末から開始したPLCでmrubyの企画ですが、今年中になんとか実用的なところまで持っていきたい気持ちになっているので、今年の抱負として「完遂」を掲げました。
本年もよろしくお願いいたします。
_ PLCでmruby (6) rite_binary_header
mrbファイルの先頭にはRITEヘッダーデータがあるということで、該当する箇所を探してみます。
dmup.hファイルにrite_binary_headerという構造体がありました。
/* binary header */
struct rite_binary_header {
uint8_t binary_ident[4]; /* Binary Identifier */
uint8_t major_version[2]; /* Binary Format Major Version */
uint8_t minor_version[2]; /* Binary Format Minor Version */
uint8_t binary_crc[2]; /* Binary CRC */
uint8_t binary_size[4]; /* Binary Size */
uint8_t compiler_name[4]; /* Compiler name */
uint8_t compiler_version[4];
};
これを元に調べてみましょう。
CRCとSizeはバイナリーデータでBig Endianになっている様です。
Rubyで調べるコードをこの様に書いて
codes = File.read "a.mrb"
binary_ident = codes[0, 4]
major_version = codes[4, 2]
minor_version = codes[6, 2]
crc = codes[8, 2].unpack("n")
size = codes[10, 4].unpack("N").first
compiler_name = codes[14, 4]
compiler_version = codes[18, 4]
pp binary_ident: binary_ident, major_version: major_version, minor_version: minor_version, crc: crc, size: size, compiler_name: compiler_name, compiler_version: compiler_version
出力されたのがこちらです。
% ruby read_rite_head.rb
{:binary_ident=>"RITE",
:major_version=>"01",
:minor_version=>"01",
:crc=>27764,
:size=>85,
:compiler_name=>"MATZ",
:compiler_version=>"0000"}
RITEというIDがあってバージョンは1.1、サイズは85バイト、コンパイラはMATZ、コンパライバージョンは0ということがわかりました。
サイズの85はファイルのサイズと一致していてヘッダーの先頭からフッター(多分あるでしょう)まで含んだサイズになっていることがわかります。
Amazon | Apple Lightning - USB 3カメラアダプタ | Apple(アップル) | USBアダプタ 通販
2020年12月23日 [長年日記]
_ PLCでmruby (5) mrbファイル
今回はmrbファイルの中をみていきます。
前回確認した時はこの様になっていました。
RITE0101ltUMATZ0000IREP&039gLVARaEN%
これでは訳がわからないので、hexdumpでちゃんと確認してみます。
% hexdump -C a.mrb
00000000 52 49 54 45 30 31 30 31 6c 74 00 00 00 55 4d 41 |RITE0101lt...UMA|
00000010 54 5a 30 30 30 30 49 52 45 50 00 00 00 26 30 33 |TZ0000IREP...&03|
00000020 30 30 00 00 00 1a 00 02 00 03 00 00 00 00 00 08 |00..............|
00000030 08 02 01 01 02 39 02 67 00 00 00 00 4c 56 41 52 |.....9.g....LVAR|
00000040 00 00 00 11 00 00 00 01 00 01 61 00 00 45 4e 44 |..........a..END|
00000050 00 00 00 00 08 |.....|
00000055
ASCIIとして有効な文字が繋がっていただけで、中身はバイナリーデータになっていました。
これはC言語様に出力した内容(codes配列)とも一致しています。
#include <stdint.h>
#ifdef __cplusplus
extern const uint8_t codes[];
#endif
const uint8_t codes[] = {
0x52,0x49,0x54,0x45,0x30,0x31,0x30,0x31,0x6c,0x74,0x00,0x00,0x00,0x55,0x4d,0x41,
0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x26,0x30,0x33,
0x30,0x30,0x00,0x00,0x00,0x1a,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x08,
0x08,0x02,0x01,0x01,0x02,0x39,0x02,0x67,0x00,0x00,0x00,0x00,0x4c,0x56,0x41,0x52,
0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x01,0x61,0x00,0x00,0x45,0x4e,0x44,
0x00,0x00,0x00,0x00,0x08,
};
この内容をどう解釈していくかということですが、こちらのスレッドが参考になりそうです。
[RFC] Update .mrb file format · Issue #944 · mruby/mruby · GitHub
どうやら最初にRITEヘッダーがある様です。
次回はRITEヘッダーを確認していきます。
Amazon Music - マライア・キャリーのAll I Want for Christmas Is You - Amazon.co.jp
2020年12月20日 [長年日記]
_ PLCでmruby (4) ニーモニック変換に方針転換
mrubyをPLCで動かすにはmrubyのVirtual Machineを実装すればできると思っていましたが、前回の出力をみるとmrubyのニーモニックからラダーのニーモニックに変換するのが手取り早い気がします。
ニーモニック変換器を作ることを当面の目標としましょう。
前回の出力を再掲します。
% mrbc --verbose a.rb
00001 NODE_SCOPE:
00001 local variables:
00001 a
00001 NODE_BEGIN:
00001 NODE_ASGN:
00001 lhs:
00001 NODE_LVAR a
00001 rhs:
00001 NODE_INT 1 base 10
irep 0x7f897b4059c0 nregs=3 nlocals=2 pools=0 syms=0 reps=0 iseq=8
local variable names:
R1:a
file: a.rb
1 000 OP_LOADI_1 R2
1 002 OP_MOVE R1 R2 ; R1:a
1 005 OP_RETURN R2
1 007 OP_STOP
これなら、ラダーで下の様な感じで作れれば置き換えができそうです。(ニーモニックは特定のPLCではなく雰囲気です)
ただ、クラスなど絡んでくるとそんなに簡単ではなく、難しいことは予想されます。
LD ON
@SET SCOPE
LD SCOPE
MOV #1, R2
MOV R2, R1
RST SCOPE
2020年12月16日 [長年日記]
_ PLCでmruby (3) mrbcコマンド
前回はmrubyとmirbコマンドを使いましたが、今度はmrbcコマンドを使ってみます。
まずは簡単なmrubyプログラムa.rbを準備します。
a = 1
変数aに整数1を代入するだけのプログラムです。
mrbcコマンドでmrubyの中間表現のmrbファイルを生成します。
% mrbc a.rb
mrbファイルを見てみると何のことかさっぱりわかりません。 先行き不安です。
RITE0101ltUMATZ0000IREP&039gLVARaEN%
mrbのBオプションを使うとC言語でリンクできるバイト列の配列を生成します。
% mrbc -Bcodes a.rb
codes配列のデータはバイト列っぽいですね、これだけ見てもやっぱりさっぱりわかりません。
#include <stdint.h>
#ifdef __cplusplus
extern const uint8_t codes[];
#endif
const uint8_t codes[] = {
0x52,0x49,0x54,0x45,0x30,0x31,0x30,0x31,0x6c,0x74,0x00,0x00,0x00,0x55,0x4d,0x41,
0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x26,0x30,0x33,
0x30,0x30,0x00,0x00,0x00,0x1a,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x08,
0x08,0x02,0x01,0x01,0x02,0x39,0x02,0x67,0x00,0x00,0x00,0x00,0x4c,0x56,0x41,0x52,
0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x01,0x61,0x00,0x00,0x45,0x4e,0x44,
0x00,0x00,0x00,0x00,0x08,
};
mrbcにverboseオプションを付けて実行してみます。
% mrbc --verbose a.rb
00001 NODE_SCOPE:
00001 local variables:
00001 a
00001 NODE_BEGIN:
00001 NODE_ASGN:
00001 lhs:
00001 NODE_LVAR a
00001 rhs:
00001 NODE_INT 1 base 10
irep 0x7f897b4059c0 nregs=3 nlocals=2 pools=0 syms=0 reps=0 iseq=8
local variable names:
R1:a
file: a.rb
1 000 OP_LOADI_1 R2
1 002 OP_MOVE R1 R2 ; R1:a
1 005 OP_RETURN R2
1 007 OP_STOP
なんかアセンブリ言語の様な出力が出てきました。 これなら何とか読んでいけそうな気がします。
2020年12月14日 [長年日記]
_ PLCでmruby (2) mrubyとは
mrubyをPLCで動かすにはmrubyのVirtual Machineを実装すればできると思うのですが、果たしてできるのか…
まずはmrubyとはなんぞや?ということです。
こちらのGitHubからCODEボタン>Download ZIPを選んでファイル一式ダウンロードします。gitが使える場合はcloneしても良いです。
GitHub - mruby/mruby: Lightweight Ruby
Mac前提で話を進めると、展開したフォルダーでminirakeコマンド(rakeでもいいです)を実行するとbinディレクトリ以下にmruby関連の実行ファイルが生成されます。
% cd path_to_your_downloaded_mruby
% ./minirake
% ls bin
mirb mrbtest mruby-config
mrbc mruby mruby-strip
Homeのbinにコピーします。
% cp bin/* ~/bin
使っているターミナルのshellに合わせて.zshrcや.bashrcに以下を追加しパスを通します。
export PATH=$PATH:$HOME/bin
ターミナルを起動し直してmruby
を実行しputs 'Hello, world'
を入力後^D
(controlを押しながらDを押す)を入力すると実行されてHello, world
が表示されます。
% mruby
puts 'Hello, world'
^D
Hello, world
Hello, worldが表示され動作確認ができます。
通常はmirbコマンドでインタラクティブに行います。
% mirb
mirb - Embeddable Interactive Ruby Shell
> puts 'Hello, world'
Hello, world
=> nil
>
2020年12月09日 [長年日記]
_ PLCでmruby (1) PLCでmrubyは動かせるのか?
いつもの如く企画倒れ前提でスタートしますが、mrubyをPLCで動かせないかなという企画です。
このシリーズはこちらのリンクで見れます。
mrubyをPLCで動かせないかな〜という企画
mrubyとは
mrubyは平たくいうと組み込み用途でも利用できる様に軽量化されたrubyです。
GitHub - mruby/mruby: Lightweight Ruby
mrubyはコマンドを入力しながら実行するインタプリター機能があるのですが、更にその機能を除いたリソースの少ないマイコンでも動かせる様にしたmruby/cがあります。
GitHub - mrubyc/mrubyc: mruby/c is an another implementation of mruby.
mruby/cならPLCでも動かせる可能性があるかもしれないということでドンキホーテーの様に挑んで行く予定ですが、3回くらいで伸されて終了になるかも知れません。
一応今までやってきたLadder DriveやPLC間の変換の経験が生かせるのではないかと思ってます。
まずは、mruby/cを動かせるほどのリソースがPLCにあるのか?、動いたとして実用的なものか?という疑問もありますが、やってみないことには判断つきません。
諦めなかったら長期戦になると思います。
Amazon | 三菱電機 FX3G-14MR/ES FXシリーズシーケンサ 基本ユニット(AC電源・DC入力タイプ) NN | 電設用部品・資材 | 産業・研究開発用品 通販