SNSへはこちら

MacでRL78の開発環境を作る

長らくブレッドボードの肥やしになっていたマイコンがあります。それは、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 特有のものを含めています。

  1. スタックポインタの初期化
  2. ES レジスタのゼロ初期化
  3. .data セクションのコピー
  4. .bss セクションのゼロ初期化
  5. (C++) .preinit_array を実行
  6. (C++) .init_array を実行
  7. main を呼び出し
  8. (C++) .fini_array を実行
  9. 無限ループ

  10. は 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 でこれまで動いていないという歯がゆい状態でしたが、なんとか実用まで持ってこれました!皆さんどうぞお試しください。