Applilet EZ PL for RL78 V1.0J, V2.00J を試してみました。
デジタル回路版電子ブロックという感じで興味深いツールと思いましたが、少々使いづらい点もあったので改善要望として挙げておきます。
> 本ツールは評価版です。本ツールに関するテクニカルサポートは受け付けておりません。
と明記されていることは理解しており、返答等を求めているものではありません。
・部品ボックス・ウィンドウのロジック IC パネルが分かりづらい
部品ボックス・ウィンドウのロジック IC パネルは以下のような内容となっていますが
分かりづらいです。マニュアルには各パネルの機能も書かれてはいますが、ロジック IC の型番と機能を関連付けて理解しているユーザを前提としているようで、Applilet EZ PL for RL78 の謳い文句にある
> 本ソフトウェアを利用することにより、プログラミング言語になじみが無くソフトウェア開発経験が無いユーザーでも、PC上でのGUI操作でマイコン応用プログラムを簡単に作成できます。
とは遠い印象です。
74HC00: 2-Input NAND 74HC02: 2-Input NOR 74HC10: 3-Input NAND 74HC11: 3-Input AND 74HC20: 4-Input NAND 74HC21: 4-Input AND 74HC27: 3-Input NOR 74HC30: 8-Input NAND 74HC51: 2/3-Input AND-OR-NOT 74HC77: 4-bit Bistable Latch 74HC112: J-K FF with Clear, Preset and Clock 74HC133: 13-Input NAND 74HC138: 3-to-8 Line Decoder 74HC148: 8-to-3 Priority Encoder 74HC153: 4-Channel Multiplexer 74HC166: 8-bit Parallel-in/Serial-out Shift Register 74HC280: 9-bit Parity Generator 74HC283: 4-bit Binary Full Adder 74HC4002: 4-Input NOR 74HC4072: 4-Input OR 74HC4075: 3-Input OR 74HC4078: 8-Input OR/NOR 74HC4511: BCD-to-7-Segment Latch 74HC7266: 2-Input XNOR
等表示できないでしょうか。日本語であれば尚良いと思います。
2018/05/08 追記:
V2.20 を確認致しました。
ロジック IC の型番と併せて機能が表示されるようになり分かりやすくなったと思います。
・ロジック IC パネルの回路数が不統一
ロジック IC パネルの内容は 74シリーズを基にしたものとなっています。
74HC00 を選択すると実際の IC であれば 4回路入っている NAND が Applilet EZ PL for RL78 では 1つの NAND 回路となっており、その他のロジック IC パネルも凡そ同等で、実際の IC では複数の回路が入っているものが 1つだけを取り出した形でパネル化されているようです。
その中で 74HC51 は 実際の IC では 2回路が含まれる ものですが、Applilet EZ PL for RL78 でも他のロジック IC パネルとは違い 2回路がセットとなっており、
仕様として統一がされていない感じです。統一された方が良いと思います。
勘違いなのでナシ。
・ROM 消費量が多い
Applilet EZ PL for RL78 V2.00J + CC-RL V1.04.00 を使用し、R5F10Y16ASP(RL78/G10 10ピン ROM 2kB)をターゲットとして選択し、ちょっと何かを作るとすると簡単に 2kB のサイズを超えてしまい ます。
R5F10Y17ASP(RL78/G10 10ピン ROM 4kB)にターゲットを変更して「生成」をしなおすと成功したりしますが、実際のところターゲット変更は手軽にできるものではないのでできれば避けたいところです。
試したプロジェクトの .map ファイルを見てみると、
_MOV1_ 0000013b 0 none ,g 0 _NOT1_ 0000013c 0 none ,g 0 _WAIT 00000143 0 none ,g 0 _Port_Set 000001b9 0 none ,g 0 _MD_INTTM00 0000020c 0 none ,g 0 _MD_INTP0 0000021d 0 none ,g 0 _MD_INTP1 0000021f 0 none ,g 0 _ANDF 0000047f 0 none ,g 0 _ORF 0000048d 0 none ,g 0 _XORF 0000049b 0 none ,g 0 _IC_74HC138_Judge_Enable 000004a2 0 none ,g 0 _IC_74HC138_Out_Y0 00000500 0 none ,g 0 _IC_74HC138_Out_Y1 0000050b 0 none ,g 0 _IC_74HC138_Out_Y2 00000516 0 none ,g 0 _IC_74HC138_Out_Y3 00000524 0 none ,g 0 _IC_74HC138_Out_Y4 00000532 0 none ,g 0 _IC_74HC138_Out_Y5 00000540 0 none ,g 0 _IC_74HC138_Out_Y6 0000054e 0 none ,g 0 _IC_74HC138_Out_Y7 0000055c 0 none ,g 0 _PWM_CH2_Init 000008f6 0 none ,g 0 _PWM_CH3_Init 000008f7 0 none ,g 0 _PWM_Out_CH2 000008f8 0 none ,g 0 _PWM_Out_CH3 000008f9 0 none ,g 0
とりあえずこれだけの使用されていない関数が無駄に ROM に配置されていました。ROM の消費量が多いことの一因ではないかと思います。
Applilet EZ PL for RL78 と併せて使用したツールチェーン CC-RL にリンク時に未使用オブジェクト(関数、変数、定数)を削除する機能がないことが直接の原因とは思いますが、それであれば、Applilet EZ PL for RL78 のライブラリとして定義される関数や変数はソースレベルでバラバラにしてコンパイルし一旦ライブラリファイルにまとめ、それをリンクすることで無駄なオブジェクトのリンクを避ける方法もあるのではないでしょうか。
訂正 後の Reply で NoMaYさんの指摘されている CC-RL の未参照オブジェクトを削除する機能を上手く使用すればサイズ縮小に役立つのではないでしょうか。
・エラーが意味不明
Applilet EZ PL for RL78 V2.00J で「生成」を行った場合、
コンパイルを開始します。 ---------- Pass1 ---------- ---------- Pass2 ---------- ---------- Pass3 ---------- コンパイルが終了しました。 使用ROMサイズ 2600byte
成功するとアウトプット・ウィンドウに以上のようなメッセージが出力され、「生成」が成功したことが分かりますが、成功しなかった場合、
コンパイルを開始します。 ---------- Pass1 ---------- ---------- Pass2 ---------- src\74hc.c(284):W0520177:変数 "ucEnable" は宣言されましたが参照されていません。 W0561120:Section address is not assigned to ".text" F0563100:Section address overflow out of range : ".text" The evaluation period has expired. Renesas Optimizing Linker Abort 2017-04-29 01:10:11 C:\Users\fujita\My Documents\Applilet EZ PL for RL78\Project\test2\makeprj.bat 2017-04-29 01:10:11 1105:Build processing error. コンパイルを中断しました。
以上のような出力となります。
マイコン開発の経験のある人であれば .text セクションのサイズが溢れてリンクエラーになったことはわかるかもしれませんが Applilet EZ PL for RL78 の想定している「プログラミング言語になじみが無くソフトウェア開発経験が無いユーザー」には難しいのではないでしょうか。それらのユーザーに理解されるようなエラーメッセージの出力が必要と思います。
・スタック領域が無駄に設定される
Applilet EZ PL for RL78 V2.00J + CC-RL V1.04.00 を使用しています。
プロジェクトの src/cstart.asm の中で
.SECTION .sdataR, DATA $IF (__RENESAS_VERSION__ < 0x01010000) ; for CC-RL V1.00 ; !!! [CAUTION] !!! ; The start address of RAM depend on the device in use. ; See the user's manual of the device. ; ex. R5F10Y14ASP -> 0x0FFE60 RAM_ADDR_START .EQU 0x0FFE60 ; Start address of RAM (SAMPLE) RAM_ADDR_END .EQU 0x0FFEE0 ; End address of RAM +1 ;----------------------------------------------------------------------------- ; stack area ;----------------------------------------------------------------------------- ; !!! [CAUTION] !!! ; Set up stack size suitable for a project. .SECTION .stack_bss, BSS _stackend: .DS 0x40 _stacktop: $ENDIF
と書かれている箇所があります。これは CC-RL 1.00 を使用した場合にスタック領域をこゝで定義するというもので、今回使用した CC-RL V1.04.00 では不要のものです。マクロ __RENESAS_VERSION__ が適切に定義されていることを前提としていますが、この __RENESAS_VERSION__ というマクロは CC-RL のマニュアルに拠ると
11.3.6 アセンブリ・ソース・ファイルで有効な定義済みマクロ コンパイルドライバからアセンブラを起動する場合,アセンブリ・ソース・ファイルで定義済みマクロ__RENESAS_VERSION__ が有効になります。
とあり、コンパイルドライバを使用せずに直接 asrl コマンドを使用してアセンブルを行っている Applilet EZ PL for RL78 V2.00J ではこのマクロが定義されず正常機能していません。結果、使用されないスタック領域が無駄に定義されており、メモリの無駄遣いとなってしまっています。
アセンブルの際にもコンパイルドライバを使用するよう変更されゝばこの問題は解消するのではないでしょうか。
・ビット単位で状態を保存する変数の定義の誤り
次のようなデジタル入力が 8つあるプロジェクトを作成し「生成」を行うと
デジタル入力の数が include/config.h に
#define DGIN_USED (8)
というマクロが定義され、ビット単位で状態を保存する変数が src/digitalio.c に
UCHAR g_ucDGIN_LastRet[(DGIN_USED / 8) + 1];
と定義されます。
DGIN_USED が 8 の際に (DGIN_USED / 8) + 1 は 2 であり、16ビット分の領域を確保することとなるので RAM の無駄遣いではないでしょうか。上記変数の定義部分は
UCHAR g_ucDGIN_LastRet[(DGIN_USED + 7) / 8];
が正しいと思います。
そもそもの話としてビット単位で状態を保存することに疑問があります。現状の Reply to Applilet EZ PL for RL78 は RAM よりも ROM の使用量に余裕がありません。状態をビット単で保存することは RAM の使用量を節約する半面コードサイズが増大しますが、必要なアプローチは逆なのではないかと思います。バイト単位の変数に 0x00 か 0x01 を保存する方式とし、RAM の使用量を無駄にしてもコードサイズを抑えるべきと思います。
・書き込み方法がお手軽でない
現状の Applilet EZ PL for RL78 はマイコンへの書き込み装置として E1 が必須となっているようですが、Applilet EZ PL for RL78 の謳い文句にある「お手軽・安価なプログラム開発環境」としては E1 は専門的な装置であり、お手軽さや安価からは遠い印象です。
Applilet EZ PL for RL78 V2.00 のターゲットとしているマイコン RL78/G10 や RL78/G11 はどちらも書き込み方法としてシリアル・プログラミングをサポートしており、その方法に使用できそうな安価な USB シリアル変換装置も販売されているようです。そういった装置にも対応されゝば Applilet EZ PL for RL78 の利用される機会も増えるのではないでしょうか。
・コードがサイズ的に冗長
Applilet EZ PL for RL78 V2.0 + CC-RL V1.04.00 を使用し、マイクロコントローラ設定を
とし、
上記の内容のプロジェクトで「生成」を行ったところ、
コンパイルを開始します。 ---------- Pass1 ---------- ---------- Pass2 ---------- src\74hc.c(284):W0520177:変数 "ucEnable" は宣言されましたが参照されていません。 W0561120:Section address is not assigned to ".text" F0563100:Section address overflow out of range : ".text" The evaluation period has expired. Renesas Optimizing Linker Abort 2017-05-02 16:51:14 C:\Users\fujita\My Documents\Applilet EZ PL for RL78\Project\test2\makeprj.bat 2017-05-02 16:51:14 1105:Build processing error. コンパイルを中断しました。
とエラーが出力され、生成に失敗しました。
ROM 容量不足のようなので、マイクロコントローラ設定の「デバイス」を、ROM 容量が 2kB の R5F10Y16ASP から 4kB の R5F10Y17ASP に変更して再度「生成」を行ったところ
成功しました。
使用 ROM サイズが 2600byte ということで、R5F10Y16ASP の ROM には収まらなかったようです。
Applilet EZ PL for RL78 では R5F10Y16ASP をサポートしていますが、上記の例は内容的にも単純なものであり、この程度のものは動作して欲しいところです。
生成時に作成される .map ファイル等を見てみると、サイズが数バイトという関数が複数生成されており、コードサイズ増大の一因となっているようです。
例:
_MOV1_: D7 ret _NOT1_: 91 dec a F6 clrw ax 61E8 skz E6 onew ax 60 mov a, x D7 ret _ByteMemGet: 14 movw de, ax 62 mov a, c 318E shrw ax, 8+0x00000 05 addw ax, de 14 movw de, ax 89 mov a, [de] D7 ret _ByteMemSet: 14 movw de, ax 62 mov a, c 318E shrw ax, 8+0x00000 05 addw ax, de 14 movw de, ax 63 mov a, b 99 mov [de], a D7 ret _Port_Set: C1 push ax C7 push hl 60 mov a, x 340100 movw de, #0x0001 73 mov b, a D3 cmp0 b DD00 bz $.BB@LABEL@8_2 .BB@LABEL@8_1: 15 movw ax, de 01 addw ax, ax 14 movw de, ax 93 dec b DF00 bnz $.BB@LABEL@8_1 .BB@LABEL@8_2: 64 mov a, e 77 mov h, a 8803 mov a, [sp+0x03] 70 mov x, a 53FF mov b, #0xFF 63 mov a, b 14 movw de, ax 92 dec c 89 mov a, [de] 70 mov x, a DF00 bnz $.BB@LABEL@8_4 .BB@LABEL@8_3: 67 mov a, h 6160 or x, a EF00 br $.BB@LABEL@8_5 .BB@LABEL@8_4: 67 mov a, h 7CFF xor a, #0xFF 6150 and x, a .BB@LABEL@8_5: 60 mov a, x 9800 mov [sp+0x00], a .BB@LABEL@8_6: 8803 mov a, [sp+0x03] 70 mov x, a 63 mov a, b 14 movw de, ax 8800 mov a, [sp+0x00] 99 mov [de], a 1004 addw sp, #0x04 D7 ret _Port_Get: C1 push ax 8801 mov a, [sp+0x01] 70 mov x, a 51FF mov a, #0xFF 14 movw de, ax 89 mov a, [de] 318E shrw ax, 8+0x00000 14 movw de, ax 8800 mov a, [sp+0x00] 73 mov b, a D3 cmp0 b DD00 bz $.BB@LABEL@9_2 .BB@LABEL@9_1: 15 movw ax, de 311E shrw ax, 0x01 14 movw de, ax 93 dec b DF00 bnz $.BB@LABEL@9_1 .BB@LABEL@9_2: 64 mov a, e 5C01 and a, #0x01 C6 pop hl D7 ret _NOTF: 91 dec a F6 clrw ax 61E8 skz E6 onew ax 60 mov a, x D7 ret _ANDF: 91 dec a E1 oneb a 61E8 skz F1 clrb a 90 dec x E0 oneb x 61E8 skz F0 clrb x 6150 and x, a 60 mov a, x D7 ret _ORF: 91 dec a E1 oneb a 61E8 skz F1 clrb a 90 dec x E0 oneb x 61E8 skz F0 clrb x 6160 or x, a 60 mov a, x D7 ret _XORF: 6148 cmp a, x E1 oneb a 61F8 sknz F1 clrb a D7 ret
ソースコードを参照すると
UCHAR MOV1_( UCHAR Fin ) { return Fin; } UCHAR NOT1_( UCHAR Fin ) { return (Fin == HIGH) ? LOW : HIGH; } UCHAR ByteMemGet( UCHAR* memp, UCHAR count ) { UCHAR work; work = (UCHAR)(*(memp + count)); return(work); } void ByteMemSet( UCHAR* memp, UCHAR count, UCHAR value ) { UCHAR* work; work = memp + count; *work = value; } void Port_Set( UCHAR Port, UCHAR TermNum, UCHAR Val ) { volatile UCHAR *ucp_port; UCHAR ucport; UCHAR ucset = Val; ucp_port = &P0; ucp_port += Port; ucport = *ucp_port; ucset = 1; ucset <<= TermNum; if (Val == HIGH){ ucport |= ucset; }else{ ucport &= ~ucset; } *ucp_port = ucport; } UCHAR Port_Get( UCHAR Port, UCHAR TermNum ) { volatile UCHAR *ucp_port; UCHAR ucport; UCHAR ucret; ucp_port = &P0; ucp_port += Port; ucport = *ucp_port; ucret = (ucport >> TermNum) & 0x01; return(ucret); } UCHAR NOTF( UCHAR in ) { return (in == HIGH)? LOW : HIGH; } UCHAR ANDF( UCHAR in1, UCHAR in2 ) { if((in1 == HIGH) && (in2 == HIGH)) return HIGH; else return LOW; } UCHAR ORF( UCHAR in1, UCHAR in2 ) { if((in1 == HIGH) || (in2 == HIGH)) return HIGH; else return LOW; } UCHAR XORF( UCHAR in1, UCHAR in2 ) { if(in1 != in2) return HIGH; else return LOW; }
短い関数が実際に用意されていますが、この程度の単純な関数であれば呼び出しに要するコードの方がサイズでは問題となり得るのでマクロ等で実装されたら良いのではないかと思います。
#define MOV1_( Fin ) (Fin) #define NOT1_( Fin ) (HIGH - (Fin)) #define ByteMemGet(memp, count) (*((memp) + (count))) #define ByteMemSet( memp, count, value ) do {*((memp) + (count)) = value;} while (0) #define Port_Set( Port, TermNum, Val ) do { if (Val) {(&P0)[(Port)] |= (1 << (TermNum));} else {(&P0)[(Port)] &= ~(1 << (TermNum));}} while (0) #define Port_Get( Port, TermNum ) (((&P0)[(Port)] >> (TermNum)) & 0x01) #define NOTF( in ) ((in) ^ 1) #define ANDF( in1, in2 ) ((in1) & (in2)) #define ORF( in1, in2 ) ((in1) | (in2)) #define XORF( in1, in2 ) ((in1) ^ (in2))
他、数バイトのサイズの関数でなくとも、初期化を行う XXX_Init() や XXX_Initialize() といった関数は一度しか呼ばれないものなのでこういったものもマクロ(若しくはインライン関数)化すると call ~ ret 文のコードサイズの削減が期待できます。
他、.map ファイルを見てみると
SECTION=.RLIB FILE=memset 00000915 00000922 e _memset 00000915 0 none ,g 2 FILE=_COM_lmul 00000923 0000096b 49 __COM_lmul 00000923 0 none ,g 3 FILE=_COM_ucdiv 0000096c 00000983 18 __COM_ucdiv 0000096c 0 none ,g 1 FILE=_COM_ucrem 00000984 00000998 15 __COM_ucrem 00000984 0 none ,g 1 FILE=_COM_uldiv 00000999 000009e9 51 __COM_uldiv 00000999 0 none ,g 3 FILE=_COM_ulrem 000009ea 00000a36 4d __COM_ulrem 000009ea 0 none ,g 3
標準ライブラリのコードサイズも案外あるようです。 memset() や乗除算は仕方がないとして、剰余は再考の余地がありそうです。 例として、
UCHAR PWM_Calc_Duty( UCHAR regTDR00L ) { ULONG ulwork1 = 0; UCHAR ucwork2 = 0; UCHAR ucwork3 = 0; ulwork1 = regTDR00L; ulwork1 = (ulwork1 + 1) * tblgPWM[ucgPWM_Cnt].SetDuty; ucwork2 = (UCHAR)(ulwork1 % 100); ucwork3 = (UCHAR)(ulwork1 / 100); if (ucwork2 >= 50) ucwork3 ++; if (ucwork3 == 0) ucwork3 ++; return ucwork3; }
の中の
ucwork2 = (UCHAR)(ulwork1 % 100); ucwork3 = (UCHAR)(ulwork1 / 100);
の部分は、
ucwork3 = (UCHAR)(ulwork1 / 100); ucwork2 = ulwork1 - ucwork3 * 100;
と変更することで剰余演算を無くすことができます。
他、例えば
UCHAR IC_74HC138_Evaluate( UCHAR G1_in, UCHAR G2A_in, UCHAR G2B_in, UCHAR A_in, UCHAR B_in, UCHAR C_in ) { UCHAR ucRet = 0b11111111; UCHAR ucEnable = LOW; if(G1_in == HIGH){ if ((G2A_in | G2B_in)==0){ ucRet = 0; switch(A_in + (B_in << 1) + (C_in << 2)){ case 0: ucRet = 0b11111110; break; case 1: ucRet = 0b11111101; break; case 2: ucRet = 0b11111011; break; case 3: ucRet = 0b11110111; break; case 4: ucRet = 0b11101111; break; case 5: ucRet = 0b11011111; break; case 6: ucRet = 0b10111111; break; case 7: ucRet = 0b01111111; break; default: ucRet = 0b11111111; } } } return ucRet; }
は
UCHAR IC_74HC138_Evaluate( UCHAR G1_in, UCHAR G2A_in, UCHAR G2B_in, UCHAR A_in, UCHAR B_in, UCHAR C_in ) { UCHAR ucRet = 0b00000000; if(G1_in && !G2A_in && !G2B_in){ ucRet = 0b00000001; if (A_in) { ucRet <<= 1; } if (B_in) { ucRet <<= 2; } if (C_in) { ucRet <<= 4; } } return ~ucRet; }
の様に書き換えるとコードサイズの縮小ができます(80バイト → 40バイト)。
以上のようなコードサイズの縮小が可能な部分は散見されるので、全体を見直しをしていただきたいと思います。先に挙げた 2600バイトとなった例ですが、半分の 1300バイト程度には縮小できる印象です。
・サンプル・プロジェクトの不在
サンプル・プロジェクト的なものが存在せず、マニュアルを見ても一通りの操作方法が説明されているのみで、取っ掛かりとして不親切な気がします。
一通りの機能をサンプル・プロジェクトとして例示し、必要な ROM 容量等も予め明らかになっていれば、ユーザから見てツールの有用性の判断にも一役買うのではないでしょうか。