SNSへはこちら

RAマイコンを試食(3) - 書き込み成功!書き込みソフトの作成

その後、chip1stop で RA マイコンを購入しましたが、1つもマイコンを殺すこと無く、動作させることに成功しました!

本記事では、殺さなくする方法書き込みソフトの公開を行っていきます。

マイコンを殺さなくする方法

変なネーミングですが、実際生きるか死ぬかなので死活問題です。やはり前回述べた謎領域がミソでした。

OPTとMPU

前回の記事では 0x400 〜 0x43B が該当の部分と述べましたが、もっと詳しく見てみます。

0x400 〜 0x407 は OPT というオプションを書き込むレジスタ領域となっていて、比較的安全な領域です。ウォッチドッグタイマの設定や、クロック設定のための情報を書き込みます。ここは後でいじります。
一方でこれ以降の領域は MPU (メモリプロテクションユニット) と呼ばれるところになっていて、これが危険です。ここに誤った値を書き込んでしまうと、当該ブロックに対してデバッガを用いた操作も一切受け付けなくなるので文字通り死活問題です (LPC の CRP 的な感じ?)。更に、シリアルブートローダーは特定箇所が 0xFFFFFFFF 以外の値だとリセットを繰り返す仕様なため、値の書き込みは慎重に行う必要があります。

この領域を守るためのリンカスクリプト

C 言語ではこのアドレスを決め打ちしてバイナリとして書き込むことはできません。ですので、リンカスクリプトで領域を直接指定してしまうという方法を取ります。ザックリとですが、そのリンカスクリプトを御覧ください。

ENTRY(Reset_Handler)

MEMORY {
    VECTOR(rx) : ORIGIN = 0x00000000, LENGTH = 0xC0
    OPT(r) : ORIGIN = 0x00000400, LENGTH = 0x3C

    ROM(rx) : ORIGIN = 0x00000440, LENGTH = 256K - 0x440
    RAM(wx) : ORIGIN = 0x20000000, LENGTH = 16K
}

_estack = ORIGIN(RAM) + LENGTH(RAM);

SECTIONS {
    .isr_vector : {
        . = ALIGN(4);
        KEEP(*(.isr_vector))
        . = ALIGN(4);
    } > VECTOR

    .opt : {
        . = ALIGN(4);
        KEEP(obj/opt.o(.opt))
        . = ALIGN(4);
    } > OPT

    .text : {
        . = ALIGN(4);
        *(.text)
        *(.text.*)
        . = ALIGN(4);
    } > ROM
...

MEMORY コマンドで定義している OPT の部分が該当の箇所です。
続いて SECTIONS コマンドですが、OPT 領域に格納するための .opt セクションを作りました。しかも厳密に、obj/opt.o と言うファイル名からしか受け付けないと規定しました。

実際にソースファイルは src/opt.c として作り、こんな感じです。

__attribute__((section(".opt")))
const volatile unsigned int opts[] = {
    0xFFFFFFFF, // OFS0
    0xFFFFCEFF, // OFS1(HOCOFRQ=48MHz, HOCO Enabled on reset)

    0xFFFFFFFF, // SECMPUPCS0
    0xFFFFFFFF, // SECMPUPCS1
    0xFFFFFFFF, // SECMPUPCE0
    0xFFFFFFFF, // SECMPUPCE1
    0xFFFFFFFF, // SECMPUS0
    0xFFFFFFFF, // SECMPUE0
    0xFFFFFFFF, // SECMPUS1
    0xFFFFFFFF, // SECMPUE1
    0xFFFFFFFF, // SECMPUS2
    0xFFFFFFFF, // SECMPUE2
    0xFFFFFFFF, // SECMPUS3
    0xFFFFFFFF, // SECMPUE3
    0xFFFFFFFF, // SECMPUAC (16Bytes)
};

一部 OFS を弄っていますが、 SECMPU から始まる全てのレジスタは 0xFFFFFFFF にしてあります。こうすることで確実に値を固定することができました。

書き込みソフトの作成

ARM だけど天下の OpenOCD 様は RA に対応していないので、シリアルプログラマを作りました。使ったソフトは Python3 です。こういう時に楽なんだよね。大嫌いな言語だけど。

準備として、pyserial が必要です。使うためにはまずインストールしておきます。

$ sudo pip3 install pyserial

150行ほどのプログラムです。main 関数に記述しまくっている初心者丸出し感凄いですが、こちらから御覧ください。
これだけで書き込みできるなんてやっぱ Python いいですね。大嫌いだけど。

使い方はこんな感じ。特に利用可能なオプションはありません。

$ ./ra_prog.py /dev/cu.usbmodem14102 ~/Micom_Projs/RA_Proj/Register/Register.bin

=== Binary Loading ===
Binary Size: 2308
Padding 5884 bytes
==> Size Total: 8192 Bytes
Checking the designated binary...OK

=== SCI Connection ===
Sending 2 pulses...
==>Response OK!
Sending Generic Code...
==>Response OK!
Changing baud rate...
==>BaudRate changed to 921600.

=== Main Execution ===
Erasing the Flash pages required...
1...
2...
3...
4...
5...
6...
7...
8...

Writing Binary...
0:
1:
2:
3:
4:
5:
6:
7:

また、Baud Rate は驚異の 921600 なので、対応していないアダプタをご利用の方はソースコードの当該箇所を編集してください。

動いた

試験用に書いたLチカコードです。

やっと動きましたよ!!これは大きな一歩です!
書き込みソフトも自作できて大満足です。ちょっとハマるくらい気にしませんよ。だってルネサスのマイコンなんてハマってナンボですからね〜

次回はプロジェクト(開発環境)の作成です。