長らくブレッドボードの肥やしになっていたマイコンがあります。それは、RL78 です。今回は取り敢えず開発環境を(苦労して)作ってみました。
秋月で売っているもの購入したので取り敢えずそれ用に環境を作ります。が、RL78/G10 だけに関しては gcc での開発に向いていない と思います。素直に Windows で CC-RL を使いましょう。
コンパイラのビルド
またしても、GNU Tool にお世話になるという選択肢はありますが、通常の gcc にて 4.9.4 をビルドして使います。こちらに記載のあるコマンドでビルドしてください。
書き込みプログラム
使用するものは GitHub にある rl78flash です。早速クローンしましょう。
修正点
Mac ではそのままではビルドが通りませんので、いくつか修正します。また、このプログラムにはバグが有り、書き込もうとしてもエラーになるので修正箇所があります。コンパイラさんがエラーを吐かないので、かなりハマっていました。ひょっとしたら、ここを直せば Linux でも書き込み可能になるかもしれません。
まずは terminal.c です。46行目の format が異なるぞ!ということなので、2つ目の指定子を %ld
から %d
に変更します。
printf("[%ld.%d] ", tv.tv_sec, tv.tv_usec);
続いて、serial.c です。存在しないボーレートがあるぞ!ということなので(というかそもそもこんなボーレート使わない)、78行目付近のものを削除してしまいます。
const baudrate_code_t baudrates[] =
{
{ 9600, B9600 },
{ 19200, B19200 },
{ 38400, B38400 },
{ 57600, B57600 },
{ 115200, B115200 }, // ここから下4つを削除
{ 0, 0}
};
さらに同じファイルで 58行目付近の ioctl(fd, TCFLSH, TCIOFLUSH);
が Mac では使えないので、同等の命令に置換します。
tcflush(fd, TCIOFLUSH);
さあ、ここからがたちの悪いバグです。といっても直すのは簡単。同じ serial.c の中で 117行目から始まる関数 serial_set_dtr
と、 132行目から始まる関数 serial_set_rts
を見てください。
中に int command
とありますが、これはダメです。ioctl
に食わせるコマンドの型は unsigned long
と決まっているので、unsigned long command
と修正します。
あとは Makefile
のあるディレクトリに戻って make
すれば OK です。
開発に必要なファイルを作る
これだけではまだマイコンを動かすことができないので、スターツアップルーチンとリンカスクリプトを用意します。これは RL78 限定の話ではなく、ほとんどのマイコンで必要になるものです。通常はメーカー製の IDE で自動生成してくれますが、自前で開発環境を作るとなると、そうは行きません。
以前 RX マイコンの開発を Mac でやったことがありましたね。その時はちょっとズルいですが、Windows の IDE から持ってきました。そろそろこういうのには慣れてきているので、今回は自力で行きます。
ディレクトリ構成
ディレクトリ構成は以下のようにします。まぁ大体で。
LEDChika(ルートディレクトリ)
|- Makefile、リンカスクリプト、等々
|- src/ (<= ソースファイルを入れる)
|- inc/ (<= ヘッダファイルを入れる)
|- obj/ (<= コンパイルしたオブジェクトファイルが入る)
スタートアップルーチンとリンカスクリプトの用意
続いてコンパイラ標準のファイルを引っ張ってきます。スタートアップルーチンとリンカスクリプトをコピーしましょう。
$ rl78-elf-objdump -d /usr/local/rl78-elf/rl78-elf/lib/crt0.o > crt0.txt # とりあえずディスアセンブル
$ cp /usr/local/rl78-elf/rl78-elf/lib/rl78.ld linker.ld # リンカスクリプトを拝借
まずは簡単なリンカスクリプトから。ルネサス公式のユーザマニュアル ハードウェア編とソフトウェア編を参考にしながら、MEMORY
コマンドを適用していきます。SADDR
はぶっちゃけよくわからないので削除しましたw
MEMORY
コマンドだけをお見せすると、こんな感じでしょうか。スタックは上方伸長のため、適当です。
MEMORY {
VEC (r) : ORIGIN = 0x00000, LENGTH = 0x00002
IVEC (r) : ORIGIN = 0x00004, LENGTH = 0x0007c
OPT (r) : ORIGIN = 0x000c0, LENGTH = 0x00004
SEC_ID (r): ORIGIN = 0x000c4, LENGTH = 10 /* セキュリティID領域 for Debug */
ROM (r) : ORIGIN = 0x000ce, LENGTH = 2k
/* The G10 variant needs to use RAM for virtual registers. */
RAM (w) : ORIGIN = 0xffde0, LENGTH = 0x00100
STACK (w) : ORIGIN = 0xffed0, LENGTH = 0x00001
}
スタートアップルーチンは基本アセンブリで書きます(実際のところはスタックポインタの初期化が終わったらC言語に移行可能)。やることは以下の通り。RL78 特有のものを含めています。
- スタックポインタの初期化
ES
レジスタのゼロ初期化.data
セクションのコピー.bss
セクションのゼロ初期化- (C++)
.preinit_array
を実行 - (C++)
.init_array
を実行 main
を呼び出し- (C++)
.fini_array
を実行 - 無限ループ
-
は ARM や AVR では必要とせず、2. は RL78 特有です(多分いらない)。
そんなこんなでできたプロジェクトの雛形を配布します。
rl78_proj
書き込み回路
G10 シリーズでは 1線式シリアル通信のみの対応 & コマンドが他のシリーズとは異なるので、rl78flash
のリポジトリではそれ用のバイナリ(rl78g10flash
)も生成されます。今回は対象ですので、後者を使います。
それでは 1線式シリアル通信に必要な回路図ですが、ルネサス公式から出ているものはこちらです。
何やら複雑ですね。それもそうで、TXD と RXD の信号が衝突しないように、トライステート・バッファを挟む必要があるのです。しかしよく考えてみると、これは別のディスクリート素子で代用できます。この回路図から以下が分かります。
- TXD = Low ならば、TOOL0 は Low 固定
- TXD = High ならば TOOL0 は RXD 固定
これを満たす回路はダイオード + 抵抗(プルアップも兼ねる)でできます。ということで使用する回路は以下の通り。PC側のシリアル変換は FT232RL を使用しました。
ダイオードは、順方向電圧の少ないツェナーダイオードをおすすめします。
このプロジェクトでは make flash
で書き込めるようになっていますが、以下を実行すれば mot ファイルを書き込み、直後にプログラムが走ります。
$ rl78g10flash -vvvva /dev/tty.usbserial-AI0454E0 LEDChika.mot 2k
不具合
色々やっているうちに、1つ不具合を見つけたので報告します。6.4.0 以降では直接レジスタを叩く際に(即値アドレスを使用する場合)は XOR 演算をする際にアドレスがおかしくなるようです。4.9.4 での使用をオススメします。
追記: 6.4.0 と 8.2.0 での動作を確認しました。どうもリンカスクリプトに記述したスタックポインタの初期値がダメだったようで、適切なアラインメントに直したらうまく動きました。というか、これまでよく動いていたなという感じですが。
〆
はぁぁぁ、やっと RL78 マイコンが動きました!! 書き込みツールはあるものの Mac でこれまで動いていないという歯がゆい状態でしたが、なんとか実用まで持ってこれました!皆さんどうぞお試しください。